├── .gitignore ├── .vscode └── settings.json ├── CMakeLists.txt ├── README.md ├── asl-translator ├── .gitignore ├── asl-translator.opam ├── bin │ ├── dune │ └── main.ml ├── dune-project ├── lib │ ├── dune │ ├── state.ml │ └── translate.ml └── test │ ├── dune │ └── test.ml ├── in ├── adds.cap ├── adds.rem ├── addv.rem ├── ldr.cap ├── ldr.rem ├── ret.cap ├── ret.rem ├── ret2.rem └── str.cap ├── out ├── adds.asl ├── adds.cap ├── adds.rem ├── adds.remo ├── addv.asl ├── addv.rem ├── addv2.asl ├── ldr.asl ├── ldr.cap ├── ldr.rem ├── ldr2.asl ├── ret.asl ├── ret.cap ├── ret.rem ├── ret2.rem ├── str.asl └── str.cap ├── src ├── asl.cpp ├── capstone.cpp ├── context.cpp ├── context.h ├── main.cpp ├── remill.cpp ├── state.cpp ├── state.h └── translate.h └── tools ├── bulk.sh ├── env.sh ├── get_mnemonic.sh ├── glue.sh ├── log_checker.py ├── log_parser.py ├── main.ll └── post.sh /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.toptal.com/developers/gitignore/api/c++,cmake,c 2 | # Edit at https://www.toptal.com/developers/gitignore?templates=c++,cmake,c 3 | 4 | 5 | *.err 6 | 7 | build/* 8 | _build/* 9 | .cache 10 | 11 | ### C ### 12 | # Prerequisites 13 | *.d 14 | 15 | # Object files 16 | *.o 17 | *.ko 18 | *.obj 19 | *.elf 20 | 21 | # Linker output 22 | *.ilk 23 | *.map 24 | *.exp 25 | 26 | # Precompiled Headers 27 | *.gch 28 | *.pch 29 | 30 | # Libraries 31 | *.lib 32 | *.a 33 | *.la 34 | *.lo 35 | 36 | # Shared objects (inc. Windows DLLs) 37 | *.dll 38 | *.so 39 | *.so.* 40 | *.dylib 41 | 42 | # Executables 43 | *.exe 44 | *.out 45 | *.app 46 | *.i*86 47 | *.x86_64 48 | *.hex 49 | 50 | # Debug files 51 | *.dSYM/ 52 | *.su 53 | *.idb 54 | *.pdb 55 | 56 | # Kernel Module Compile Results 57 | *.mod* 58 | *.cmd 59 | .tmp_versions/ 60 | modules.order 61 | Module.symvers 62 | Mkfile.old 63 | dkms.conf 64 | 65 | ### C++ ### 66 | # Prerequisites 67 | 68 | # Compiled Object files 69 | *.slo 70 | 71 | # Precompiled Headers 72 | 73 | # Compiled Dynamic libraries 74 | 75 | # Fortran module files 76 | *.mod 77 | *.smod 78 | 79 | # Compiled Static libraries 80 | *.lai 81 | 82 | # Executables 83 | 84 | ### CMake ### 85 | CMakeLists.txt.user 86 | CMakeCache.txt 87 | CMakeFiles 88 | CMakeScripts 89 | Testing 90 | Makefile 91 | cmake_install.cmake 92 | install_manifest.txt 93 | compile_commands.json 94 | CTestTestfile.cmake 95 | _deps 96 | 97 | ### CMake Patch ### 98 | # External projects 99 | *-prefix/ 100 | 101 | # End of https://www.toptal.com/developers/gitignore/api/c++,cmake,c 102 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "cctype": "cpp", 4 | "clocale": "cpp", 5 | "cmath": "cpp", 6 | "cstdarg": "cpp", 7 | "cstddef": "cpp", 8 | "cstdio": "cpp", 9 | "cstdlib": "cpp", 10 | "cstring": "cpp", 11 | "ctime": "cpp", 12 | "cwchar": "cpp", 13 | "cwctype": "cpp", 14 | "any": "cpp", 15 | "array": "cpp", 16 | "atomic": "cpp", 17 | "bit": "cpp", 18 | "*.tcc": "cpp", 19 | "bitset": "cpp", 20 | "charconv": "cpp", 21 | "chrono": "cpp", 22 | "codecvt": "cpp", 23 | "compare": "cpp", 24 | "concepts": "cpp", 25 | "condition_variable": "cpp", 26 | "cstdint": "cpp", 27 | "deque": "cpp", 28 | "list": "cpp", 29 | "map": "cpp", 30 | "set": "cpp", 31 | "string": "cpp", 32 | "unordered_map": "cpp", 33 | "unordered_set": "cpp", 34 | "vector": "cpp", 35 | "exception": "cpp", 36 | "algorithm": "cpp", 37 | "functional": "cpp", 38 | "iterator": "cpp", 39 | "memory": "cpp", 40 | "memory_resource": "cpp", 41 | "numeric": "cpp", 42 | "optional": "cpp", 43 | "random": "cpp", 44 | "ratio": "cpp", 45 | "source_location": "cpp", 46 | "string_view": "cpp", 47 | "system_error": "cpp", 48 | "tuple": "cpp", 49 | "type_traits": "cpp", 50 | "utility": "cpp", 51 | "fstream": "cpp", 52 | "future": "cpp", 53 | "initializer_list": "cpp", 54 | "iomanip": "cpp", 55 | "iosfwd": "cpp", 56 | "iostream": "cpp", 57 | "istream": "cpp", 58 | "limits": "cpp", 59 | "mutex": "cpp", 60 | "new": "cpp", 61 | "numbers": "cpp", 62 | "ostream": "cpp", 63 | "ranges": "cpp", 64 | "semaphore": "cpp", 65 | "shared_mutex": "cpp", 66 | "span": "cpp", 67 | "sstream": "cpp", 68 | "stdexcept": "cpp", 69 | "stop_token": "cpp", 70 | "streambuf": "cpp", 71 | "thread": "cpp", 72 | "cinttypes": "cpp", 73 | "typeinfo": "cpp", 74 | "variant": "cpp", 75 | "__bit_reference": "cpp", 76 | "__bits": "cpp", 77 | "__config": "cpp", 78 | "__debug": "cpp", 79 | "__errc": "cpp", 80 | "__hash_table": "cpp", 81 | "__locale": "cpp", 82 | "__mutex_base": "cpp", 83 | "__node_handle": "cpp", 84 | "__nullptr": "cpp", 85 | "__split_buffer": "cpp", 86 | "__string": "cpp", 87 | "__threading_support": "cpp", 88 | "__tree": "cpp", 89 | "__tuple": "cpp", 90 | "format": "cpp", 91 | "ios": "cpp", 92 | "locale": "cpp", 93 | "queue": "cpp", 94 | "version": "cpp", 95 | "*.inc": "cpp", 96 | "filesystem": "cpp", 97 | "stacktrace": "cpp" 98 | }, 99 | "ocaml.sandbox": { 100 | "kind": "opam", 101 | "switch": "bap" 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | # set the project name 4 | project(llvm-translator) 5 | 6 | set(CMAKE_CXX_STANDARD 20) 7 | set(CMAKE_EXPORT_COMPILE_COMMANDS ON) 8 | 9 | find_package(LLVM 14 REQUIRED CONFIG 10 | PATHS /usr/lib/llvm14) 11 | 12 | message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") 13 | message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") 14 | 15 | execute_process(COMMAND "${LLVM_TOOLS_BINARY_DIR}/llvm-config" --libfiles core support irreader 16 | OUTPUT_VARIABLE LLVM_LIBRARY_FILES 17 | OUTPUT_STRIP_TRAILING_WHITESPACE) 18 | message(STATUS "Using LLVM libraries: ${LLVM_LIBRARY_FILES}") 19 | 20 | add_definitions(${LLVM_DEFINITIONS_LIST}) 21 | include_directories(${LLVM_INCLUDE_DIRS}) 22 | link_directories(${LLVM_LIBRARY_DIRS}) 23 | 24 | #link_libraries(${llvm_libs}) 25 | 26 | find_package(Boost REQUIRED) 27 | include_directories(${Boost_INCLUDE_DIRS}) 28 | 29 | # add the executable 30 | add_executable(llvm-translator src/main.cpp src/state.cpp src/context.cpp 31 | src/capstone.cpp src/remill.cpp src/asl.cpp) 32 | 33 | target_link_libraries(llvm-translator ${LLVM_LIBRARY_FILES}) 34 | 35 | target_compile_options(llvm-translator PRIVATE -g -fsanitize=address -Wall) 36 | target_link_options(llvm-translator PRIVATE -g -fsanitize=address) 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # llvm-translator 2 | 3 | An ad-hoc collection of pieces to compare (semantically) the output of several AArch64 lifters, namely asl-interpreter, RetDec (via Capstone), and Remill. 4 | asl-interpreter is used as the baseline for comparison. 5 | 6 | Requires: 7 | - LLVM 14 8 | - https://github.com/UQ-PAC/aslp/tree/partial_eval/, beside this directory and with folder name _asl-interpreter_. 9 | - https://github.com/AliveToolkit/alive2, beside this directory and with translation validation ([see README](https://github.com/AliveToolkit/alive2#building-and-running-translation-validation)). Commit [`bc51b72c`](https://github.com/AliveToolkit/alive2/commit/bc51b72cf5773967fd29155f1ffb251df4d5e94e) with cherry-pick [`9a7504a9`](https://github.com/AliveToolkit/alive2/commit/9a7504a99972e2c613deacaa8a4f1798829d2ff2) and LLVM 15 from [here](https://github.com/katrinafyi/pac-environment/releases/tag/llvm). 10 | - https://github.com/avast/retdec, beside and built with these commands: 11 | ```bash 12 | cd retdec 13 | git checkout v5.0 14 | curl https://gist.githubusercontent.com/katrinafyi/c33f6f9ccaad4420f76f84e6cb219fe0/raw/0001-emit-names-for-capstone-intrinsics.patch \ 15 | | git am 16 | cmake -B build -DCMAKE_INSTALL_PREFIX=$(pwd)/build/prefix -DRETDEC_DEV_TOOLS=1 -DCMAKE_CXX_FLAGS='-include cstdint' -DCMAKE_CXX_FLAGS_RELEASE='-include cstdint' 17 | cmake --build build -j5 18 | make -C build install 19 | ``` 20 | Tested with RetDec [v5.0](https://github.com/avast/retdec/tree/v5.0) with [a patch](https://gist.github.com/katrinafyi/c33f6f9ccaad4420f76f84e6cb219fe0) applied. 21 | - https://github.com/lifting-bits/remill, as "remill" Docker container. 22 | 23 | Usage: 24 | - `tools/env.sh` will set up environment variables for later use. Run this first to check the dependencies can be found correctly. 25 | - `tools/glue.sh 2100028b` performs the comparison on the opcode 2100028b. Output is printed to stdout and supplementary logs are written to /tmp. 26 | - `tools/bulk.sh logs_dir` performs the comparison on many opcodes, calling glue.sh for each one. 27 | - Progress is printed to stdout and comparison results (i.e. from glue.sh) are written to subfolders of logs_dir. 28 | - Opcodes are sourced from ../asl-interpreter/tests/coverage/\*, which has lists of opcodes liftable by the asl-interpreter. 29 | - `tools/log_parser.py logs_dir out.csv` parses the log directory logs_dir which should contain the output of bulk.sh. Results are tabulated for further analysis. 30 | 31 | Components: 32 | - asl-translator/ contains an OCaml dune project which translates asl-interpreter's reduced ASL into LLVM IR. 33 | ```bash 34 | cd asl-translator 35 | eval $(opam env) # make sure to use non-system ocaml compiler 36 | opam pin ../../asl-interpreter # path to asl-interpreter repository 37 | opam install --deps-only ./asl-translator.opam # also install LLVM 14 through system packages 38 | dune build 39 | ``` 40 | Then, dump ASL from asl-interpreter with `:dump A64 0x8b020021 /tmp/sem.aslb`, then run asl-translator with `dune exec test /tmp/sem.aslb`. 41 | - This directory (llvm-translator) is a C++ project which unifies the LLVM IR from each lifter. 42 | ```bash 43 | cmake -B build . 44 | cmake --build build 45 | ./go rem /tmp/remill_out.ll # also supports 'cap' and 'asl' 46 | ``` 47 | - tools/post.sh is used to post-process and simplify the output of llvm-translator before passing to alive. It calls opt and runs a given list of passes. 48 | - Further, Alive2 requires source/target to have the same set of global variables. llvm-translator supports `./go vars /tmp/cap.ll /tmp/rem.ll /tmp/asl.ll` which will union all variables mentioned by each lifter and insert them into the others. 49 | - in/ and out/ contain old snapshots of LLVM code, as an example of the different LLVM IR styles from each lifter. in/ is directly from the lifter in question, and out/ is after (an old version of) llvm-translator. 50 | -------------------------------------------------------------------------------- /asl-translator/.gitignore: -------------------------------------------------------------------------------- 1 | _build 2 | vgcore.* 3 | -------------------------------------------------------------------------------- /asl-translator/asl-translator.opam: -------------------------------------------------------------------------------- 1 | # This file is generated by dune, edit dune-project instead 2 | opam-version: "2.0" 3 | synopsis: "A short synopsis" 4 | description: "A longer description" 5 | maintainer: ["Maintainer Name"] 6 | authors: ["Author Name"] 7 | license: "LICENSE" 8 | tags: ["topics" "to describe" "your" "project"] 9 | homepage: "https://github.com/username/reponame" 10 | doc: "https://url/to/documentation" 11 | bug-reports: "https://github.com/username/reponame/issues" 12 | depends: [ 13 | "ocaml" 14 | "dune" {>= "3.4"} 15 | "asli" 16 | "conf-llvm" {>= "14" & < "15"} 17 | "llvm" {>= "14" & < "15"} 18 | "odoc" {with-doc} 19 | ] 20 | build: [ 21 | ["dune" "subst"] {dev} 22 | [ 23 | "dune" 24 | "build" 25 | "-p" 26 | name 27 | "-j" 28 | jobs 29 | "@install" 30 | "@runtest" {with-test} 31 | "@doc" {with-doc} 32 | ] 33 | ] 34 | dev-repo: "git+https://github.com/username/reponame.git" 35 | -------------------------------------------------------------------------------- /asl-translator/bin/dune: -------------------------------------------------------------------------------- 1 | (executable 2 | (public_name asl-translator) 3 | (name main) 4 | (libraries test) 5 | (flags (:standard -g -ccopt -g -verbose)) 6 | ) 7 | -------------------------------------------------------------------------------- /asl-translator/bin/main.ml: -------------------------------------------------------------------------------- 1 | (* let () = Test.Translate.f () *) 2 | 3 | let () = 4 | let open Test.Translate in 5 | let fname = Sys.argv.(1) in 6 | let stmts = load_aslb fname in 7 | (* List.iter (fun x -> x |> LibASL.Asl_utils.pp_stmt |> Printf.eprintf "%s\n") stmts; *) 8 | ignore @@ translate_stmts_entry stmts; 9 | 10 | Llvm.print_module "/dev/stdout" llmodule; 11 | match Llvm_analysis.verify_module llmodule with 12 | | None -> () 13 | | Some s -> failwith @@ "verify_module failed for " ^ fname ^ ": " ^ s 14 | -------------------------------------------------------------------------------- /asl-translator/dune-project: -------------------------------------------------------------------------------- 1 | (lang dune 3.4) 2 | 3 | (name asl-translator) 4 | 5 | (generate_opam_files true) 6 | 7 | (source 8 | (github username/reponame)) 9 | 10 | (authors "Author Name") 11 | 12 | (maintainers "Maintainer Name") 13 | 14 | (license LICENSE) 15 | 16 | (documentation https://url/to/documentation) 17 | 18 | (package 19 | (name asl-translator) 20 | (synopsis "A short synopsis") 21 | (description "A longer description") 22 | (depends ocaml dune asli 23 | (conf-llvm (and (>= 14) (< 15))) 24 | (llvm (and (>= 14) (< 15)))) 25 | (tags 26 | (topics "to describe" your project))) 27 | 28 | ; See the complete stanza docs at https://dune.readthedocs.io/en/stable/dune-files.html#dune-project 29 | -------------------------------------------------------------------------------- /asl-translator/lib/dune: -------------------------------------------------------------------------------- 1 | (library 2 | (name test) 3 | (modules translate state) 4 | (libraries asli.libASL llvm llvm.irreader llvm.analysis zarith) 5 | (flags (:standard -g -ccopt -g -verbose)) 6 | (ocamlc_flags (-custom))) 7 | -------------------------------------------------------------------------------- /asl-translator/lib/state.ml: -------------------------------------------------------------------------------- 1 | let state_ll = {| 2 | ; base unified state representation 3 | source_filename = "/nonexistent.ll" 4 | 5 | @X0 = global i64 0 6 | @X1 = global i64 0 7 | @X2 = global i64 0 8 | @X3 = global i64 0 9 | @X4 = global i64 0 10 | @X5 = global i64 0 11 | @X6 = global i64 0 12 | @X7 = global i64 0 13 | @X8 = global i64 0 14 | @X9 = global i64 0 15 | @X10 = global i64 0 16 | @X11 = global i64 0 17 | @X12 = global i64 0 18 | @X13 = global i64 0 19 | @X14 = global i64 0 20 | @X15 = global i64 0 21 | @X16 = global i64 0 22 | @X17 = global i64 0 23 | @X18 = global i64 0 24 | @X19 = global i64 0 25 | @X20 = global i64 0 26 | @X21 = global i64 0 27 | @X22 = global i64 0 28 | @X23 = global i64 0 29 | @X24 = global i64 0 30 | @X25 = global i64 0 31 | @X26 = global i64 0 32 | @X27 = global i64 0 33 | @X28 = global i64 0 34 | @X29 = global i64 0 35 | @X30 = global i64 0 36 | @X31 = global i64 0 37 | @V0 = global i128 0 38 | @V1 = global i128 0 39 | @V2 = global i128 0 40 | @V3 = global i128 0 41 | @V4 = global i128 0 42 | @V5 = global i128 0 43 | @V6 = global i128 0 44 | @V7 = global i128 0 45 | @V8 = global i128 0 46 | @V9 = global i128 0 47 | @V10 = global i128 0 48 | @V11 = global i128 0 49 | @V12 = global i128 0 50 | @V13 = global i128 0 51 | @V14 = global i128 0 52 | @V15 = global i128 0 53 | @V16 = global i128 0 54 | @V17 = global i128 0 55 | @V18 = global i128 0 56 | @V19 = global i128 0 57 | @V20 = global i128 0 58 | @V21 = global i128 0 59 | @V22 = global i128 0 60 | @V23 = global i128 0 61 | @V24 = global i128 0 62 | @V25 = global i128 0 63 | @V26 = global i128 0 64 | @V27 = global i128 0 65 | @V28 = global i128 0 66 | @V29 = global i128 0 67 | @V30 = global i128 0 68 | @V31 = global i128 0 69 | @SP = global i64 0 70 | @NF = global i1 false 71 | @ZF = global i1 false 72 | @CF = global i1 false 73 | @VF = global i1 false 74 | @PC = global i64 0 75 | 76 | 77 | define void @root() { 78 | ret void 79 | } 80 | 81 | |} 82 | -------------------------------------------------------------------------------- /asl-translator/lib/translate.ml: -------------------------------------------------------------------------------- 1 | open Llvm 2 | open LibASL.Asl_ast 3 | open LibASL.Asl_utils 4 | 5 | let a = 2 6 | 7 | let ctx : llcontext = Llvm.global_context () 8 | 9 | let llmodule : llmodule = Llvm_irreader.parse_ir ctx 10 | (Llvm.MemoryBuffer.of_string State.state_ll) 11 | 12 | let bool_t = i1_type ctx 13 | let bool_true = const_all_ones bool_t 14 | let bool_false = const_null bool_t 15 | let i128_t = integer_type ctx 128 16 | let void_t = void_type ctx 17 | let void_fun_t : lltype = function_type void_t [| |] 18 | 19 | let log2 x = Float.of_int x |> Float.log2 |> Float.ceil |> Int.of_float 20 | 21 | let func : llvalue = declare_function "root" void_fun_t llmodule 22 | (* let entry = entry_block func *) 23 | 24 | let translate_ty (ty: ty) : lltype = 25 | match ty with 26 | | Type_Bits (Expr_LitInt n) -> integer_type ctx (int_of_string n) 27 | | Type_Constructor (Ident "boolean") -> bool_t 28 | | Type_Register (wd, _) -> integer_type ctx (int_of_string wd) 29 | | Type_Bits _ 30 | | Type_Constructor _ 31 | | Type_OfExpr _ 32 | | Type_Array (_, _) 33 | | Type_Tuple _ 34 | | Type_App _ -> failwith @@ "translate_ty: " ^ pp_type ty 35 | 36 | let ident = function | Ident x | FIdent (x,_) -> x 37 | 38 | module Globals = Map.Make(String) 39 | let vars : llvalue Globals.t ref = ref Globals.empty 40 | 41 | 42 | let unknown_loc = LibASL.Asl_ast.Unknown 43 | let lexpr_to_expr = LibASL.Symbolic.lexpr_to_expr unknown_loc 44 | let expr_to_lexpr = LibASL.Symbolic.expr_to_lexpr 45 | 46 | (** An intentionally "unusable" llvalue. Returned where a value is required but it is never intended to be read. *) 47 | let unusable : llvalue = poison (vector_type (integer_type ctx 403 (* forbidden *)) 1) 48 | 49 | 50 | let rec translate_prim (nm: string) (tes: expr list) (es: expr list) (build: llbuilder): llvalue option = 51 | let err s = failwith @@ "translate_prim: " ^ s ^ " at " ^ pp_expr (Expr_TApply (Ident nm, tes, es)) in 52 | match nm,tes,es with 53 | 54 | | "cvt_bool_bv",_,[x] 55 | | "cvt_bv_bool",_,[x] -> 56 | Some (translate_expr x build) 57 | 58 | | "neg_bits",_,[x] -> 59 | let x = translate_expr x build in 60 | Some (build_neg x "" build) 61 | | "add_bits",_,[x;y] -> 62 | let x = translate_expr x build and y = translate_expr y build in 63 | Some (build_add x y "" build) 64 | | "sub_bits",_,[x;y] -> 65 | let x = translate_expr x build and y = translate_expr y build in 66 | Some (build_sub x y "" build) 67 | | "mul_bits",_,[x;y] -> 68 | let x = translate_expr x build and y = translate_expr y build in 69 | Some (build_mul x y "" build) 70 | | "sdiv_bits",_,[x;y] -> 71 | let x = translate_expr x build and y = translate_expr y build in 72 | Some (build_sdiv x y "" build) 73 | 74 | 75 | | ("or_bits"|"or_bool"),_,[x;y] -> 76 | let x = translate_expr x build and y = translate_expr y build in 77 | Some (build_or x y "" build) 78 | | "eor_bits",_,[x;y] -> 79 | let x = translate_expr x build and y = translate_expr y build in 80 | Some (build_xor x y "" build) 81 | | ("and_bits"|"and_bool"),_,[x;y] -> 82 | let x = translate_expr x build and y = translate_expr y build in 83 | Some (build_and x y "" build) 84 | 85 | | ("not_bits"|"not_bool"),_,[x] -> 86 | let x = translate_expr x build in 87 | Some (build_not x "" build) 88 | 89 | | "eq_bits",_,[x;y] 90 | | "eq_enum",_,[x;y] -> 91 | let x = translate_expr x build and y = translate_expr y build in 92 | Some (build_icmp Icmp.Eq x y "" build) 93 | | "ne_bits",_,[x;y] -> 94 | let x = translate_expr x build and y = translate_expr y build in 95 | Some (build_icmp Icmp.Ne x y "" build) 96 | 97 | | "slt_bits",_,[x;y] -> 98 | let x = translate_expr x build and y = translate_expr y build in 99 | Some (build_icmp Icmp.Slt x y "" build) 100 | | "sle_bits",_,[x;y] -> 101 | let x = translate_expr x build and y = translate_expr y build in 102 | Some (build_icmp Icmp.Sle x y "" build) 103 | 104 | | "lsl_bits",_,[x;y] -> 105 | let x = translate_expr x build and y = translate_expr y build in 106 | assert (integer_bitwidth (type_of x) >= integer_bitwidth (type_of y)); 107 | let y = build_zext_or_bitcast y (type_of x) "" build in 108 | Some (build_shl x y "" build) 109 | | "lsr_bits",_,[x;y] -> 110 | let x = translate_expr x build and y = translate_expr y build in 111 | assert (integer_bitwidth (type_of x) >= integer_bitwidth (type_of y)); 112 | let y = build_zext_or_bitcast y (type_of x) "" build in 113 | Some (build_lshr x y "" build) 114 | | "asr_bits",_,[x;y] -> 115 | let x = translate_expr x build and y = translate_expr y build in 116 | assert (integer_bitwidth (type_of x) >= integer_bitwidth (type_of y)); 117 | let y = build_zext_or_bitcast y (type_of x) "" build in 118 | Some (build_ashr x y "" build) 119 | 120 | 121 | 122 | | "replicate_bits",[Expr_LitInt xw; Expr_LitInt n],[x; _] when int_of_string n >= 1 -> 123 | let x = translate_expr x build in 124 | let xw = int_of_string xw and n = int_of_string n in 125 | let ty = (integer_type ctx (n * xw)) in 126 | let base = build_zext_or_bitcast x ty "" build in 127 | let rec go acc i = 128 | if i = n then begin 129 | acc 130 | end else begin 131 | let shl = build_shl base (const_int ty (i * xw)) "" build in 132 | let next = build_or shl acc "" build in 133 | go next (i+1) 134 | end 135 | in 136 | Some (go base 1) 137 | 138 | | "append_bits",[Expr_LitInt xw; Expr_LitInt yw],[x;y] -> 139 | let xw = int_of_string xw and yw = int_of_string yw in 140 | let x = translate_expr x build and y = translate_expr y build in 141 | let t = integer_type ctx (xw + yw) in 142 | let x = build_zext_or_bitcast x t "" build in 143 | let y = build_zext_or_bitcast y t "" build in 144 | let x = build_shl x (const_int t yw) "" build in 145 | Some (build_or x y "" build) 146 | 147 | | "ZeroExtend",_,[x;Expr_LitInt n] -> 148 | let x = translate_expr x build and n = int_of_string n in 149 | Some (build_zext x (integer_type ctx n) "" build) 150 | | "SignExtend",_,[x;Expr_LitInt n] -> 151 | let x = translate_expr x build and n = int_of_string n in 152 | Some (build_sext x (integer_type ctx n) "" build) 153 | 154 | (* ["LSL",0; "LSR",0; "ASR",0; "SignExtend",0; "ZeroExtend",0] *) 155 | 156 | | "LSL",_,[x;y] -> 157 | let x = translate_expr x build and y = translate_expr y build in 158 | assert (integer_bitwidth (type_of x) >= integer_bitwidth (type_of y)); 159 | let y = build_zext_or_bitcast y (type_of x) "" build in 160 | Some (build_shl x y "" build) 161 | | "LSR",_,[x;y] -> 162 | let x = translate_expr x build and y = translate_expr y build in 163 | assert (integer_bitwidth (type_of x) >= integer_bitwidth (type_of y)); 164 | let y = build_zext_or_bitcast y (type_of x) "" build in 165 | Some (build_lshr x y "" build) 166 | | "ASR",_,[x;y] -> 167 | let x = translate_expr x build and y = translate_expr y build in 168 | assert (integer_bitwidth (type_of x) >= integer_bitwidth (type_of y)); 169 | let y = build_zext_or_bitcast y (type_of x) "" build in 170 | Some (build_ashr x y "" build) 171 | 172 | 173 | 174 | | "Mem.read",_,[addr;Expr_LitInt n;_] -> 175 | let addr = translate_expr addr build and n = int_of_string n in 176 | let vty = integer_type ctx (n*8) in 177 | let ptr = build_inttoptr addr (pointer_type vty) "" build in 178 | Some (build_load ptr "" build) 179 | 180 | | "Mem.set",_,[addr;Expr_LitInt n;_;rv] -> 181 | let addr = translate_expr addr build and n = int_of_string n in 182 | let rv = translate_expr rv build in 183 | let vty = integer_type ctx (n*8) in 184 | let ptr = build_inttoptr addr (pointer_type vty) "" build in 185 | ignore @@ build_store rv ptr build; 186 | None 187 | 188 | | _ -> err "unsupported" 189 | 190 | 191 | and translate_expr (exp : expr) (build: llbuilder) : llvalue = 192 | let err s = failwith @@ "translate_expr: " ^ s ^ " at " ^ pp_expr exp in 193 | match exp with 194 | | Expr_Parens e -> translate_expr e build 195 | 196 | | Expr_Slices (base, [Slice_LoWd (Expr_LitInt lo,Expr_LitInt wd)]) -> 197 | let base = translate_expr base build in 198 | let lo = int_of_string lo and wd = int_of_string wd in 199 | let ty = type_of base in 200 | let ty' = integer_type ctx wd in 201 | 202 | let lshr = 203 | if lo = 0 204 | then base 205 | else build_lshr base (const_int ty lo) "" build 206 | in 207 | if integer_bitwidth ty' = integer_bitwidth ty 208 | then lshr 209 | else build_trunc lshr ty' "" build 210 | 211 | | Expr_Var (Ident "TRUE") -> bool_true 212 | | Expr_Var (Ident "FALSE") -> bool_false 213 | 214 | | Expr_Var _ 215 | | Expr_Array _ 216 | | Expr_Field (_, _) -> 217 | let ptr = translate_lexpr (expr_to_lexpr exp) in 218 | build_load ptr "" build 219 | 220 | | Expr_TApply (nm, tes, es) -> 221 | (match translate_prim (ident nm) tes es build with 222 | | None -> err "translate_prim returned no value" 223 | | Some x -> x) 224 | 225 | | Expr_LitInt n -> 226 | let n = int_of_string n in 227 | assert (n >= 0); 228 | let bits = 229 | if n > 0 then Float.of_int n |> Float.log2 |> Float.floor |> Float.add Float.one |> Int.of_float 230 | else 1 231 | in 232 | (* Printf.printf "n=%d,bits=%d\n" n bits; *) 233 | assert (n < Int.shift_left 1 bits); 234 | const_int (integer_type ctx bits) n 235 | | Expr_LitHex _ -> assert false 236 | | Expr_LitBits str -> 237 | let ty = integer_type ctx (String.length str) in 238 | const_int_of_string ty str 2 239 | 240 | | Expr_LitReal _ 241 | | Expr_LitMask _ 242 | | Expr_LitString _ 243 | 244 | | Expr_Slices _ 245 | | Expr_In (_, _) 246 | | Expr_If (_, _, _, _, _) 247 | | Expr_Fields (_, _) 248 | | Expr_Tuple _ 249 | | Expr_Binop (_, _, _) 250 | | Expr_Unop (_, _) 251 | | Expr_ImpDef (_, _) 252 | | Expr_Unknown _ 253 | -> err "unsupported expression" 254 | 255 | 256 | and translate_lexpr (lexp: lexpr) : llvalue = 257 | let err s = failwith @@ "translate_lexpr: " ^ s ^ " at " ^ pp_lexpr lexp in 258 | let find nm = 259 | try Globals.find nm !vars 260 | with Not_found -> err @@ "cannot find variable " ^ nm 261 | in 262 | 263 | match lexp with 264 | 265 | | LExpr_Var (Ident "_PC") -> find "PC" 266 | | LExpr_Var (Ident "SP_EL0") -> find "SP" 267 | | LExpr_Var (Ident id) when String.starts_with ~prefix:"SP_" id -> err @@ "unsupported stack pointer: " ^ id 268 | | LExpr_Var nm -> find (ident nm) 269 | 270 | | LExpr_Array (LExpr_Var (Ident "_R"), Expr_LitInt n) -> find ("X"^n) 271 | | LExpr_Array (LExpr_Var (Ident "_Z"), Expr_LitInt n) -> find ("V"^n) 272 | | LExpr_Field (LExpr_Var (Ident "PSTATE"), Ident "nRW") -> find "nRW" 273 | | LExpr_Field (LExpr_Var (Ident "PSTATE"), Ident "N") -> find "NF" 274 | | LExpr_Field (LExpr_Var (Ident "PSTATE"), Ident "Z") -> find "ZF" 275 | | LExpr_Field (LExpr_Var (Ident "PSTATE"), Ident "C") -> find "CF" 276 | | LExpr_Field (LExpr_Var (Ident "PSTATE"), Ident "V") -> find "VF" 277 | 278 | | LExpr_Array _ 279 | | LExpr_Wildcard 280 | | LExpr_Field (_, _) 281 | | LExpr_Fields (_, _) 282 | | LExpr_Slices (_, _) 283 | | LExpr_BitTuple _ 284 | | LExpr_Tuple _ 285 | | LExpr_Write (_, _, _) 286 | | LExpr_ReadWrite (_, _, _, _) -> err "unsupported" 287 | 288 | 289 | 290 | (** a tuple of entry and exit basic blocks. 291 | 292 | has the following properties: 293 | - the two blocks are linked, with the entry block 294 | suitable for entering the concept described 295 | - the exit block does not have a terminating instruction 296 | - the two blocks may refer to the same block if there is only one. 297 | *) 298 | type blockpair = llbasicblock * llbasicblock 299 | 300 | let link (first: blockpair) (second: blockpair): blockpair = 301 | let (b1, b2) = first in 302 | let (rest1, rest2) = second in 303 | ignore @@ build_br rest1 (builder_at_end ctx b2); 304 | (b1, rest2) 305 | 306 | let rec translate_stmt (stmt : LibASL.Asl_ast.stmt) : llbasicblock * llbasicblock = 307 | let err s = failwith @@ "translate_stmt: " ^ s ^ " at " ^ pp_stmt stmt in 308 | let entry = append_block ctx "stmt" func in 309 | let build = builder_at_end ctx entry in 310 | let single = (entry, entry) in 311 | 312 | match stmt with 313 | | Stmt_Assert _ -> single 314 | | Stmt_VarDeclsNoInit (ty, nms, _) -> 315 | let ty = translate_ty ty in 316 | List.iter (fun nm -> 317 | let alloc = build_alloca ty (ident nm) build in 318 | vars := Globals.add (ident nm) alloc !vars; 319 | ) nms; 320 | single 321 | 322 | | Stmt_VarDecl (ty, nm, rv, _) 323 | | Stmt_ConstDecl (ty, nm, rv, _) -> 324 | let ty = translate_ty ty in 325 | let alloc = build_alloca ty (ident nm) build in 326 | ignore @@ build_store (translate_expr rv build) alloc build; 327 | 328 | vars := Globals.add (ident nm) alloc !vars; 329 | single 330 | | Stmt_Assign (le, rv, _) -> 331 | let rv = translate_expr rv build in 332 | let rv = 333 | (match le with 334 | | LExpr_Field (LExpr_Var (Ident "_Z"), _) -> build_trunc rv i128_t "" build 335 | | _ -> rv) 336 | in 337 | ignore @@ build_store rv (translate_lexpr le) build; 338 | single 339 | | Stmt_TCall (f, tes, es, _) -> 340 | (match translate_prim (ident f) tes es build with 341 | | None -> () 342 | | Some _ -> err "translate_prim returned value in statement"); 343 | single 344 | | Stmt_If (cond, trues, elses, falses, _) -> 345 | assert (elses = []); 346 | 347 | let cond = translate_expr cond build in 348 | 349 | let t_hd,t_tl = translate_stmts trues in 350 | let f_hd,f_tl = translate_stmts falses in 351 | 352 | ignore @@ build_cond_br cond t_hd f_hd build; 353 | 354 | let exit = append_block ctx "if_merge" func in 355 | ignore @@ build_br exit (builder_at_end ctx t_tl); 356 | ignore @@ build_br exit (builder_at_end ctx f_tl); 357 | 358 | entry,exit 359 | 360 | 361 | | Stmt_Throw (_, _) -> assert false 362 | | Stmt_Unpred _ 363 | | Stmt_ConstrainedUnpred _ 364 | | Stmt_ImpDef (_, _) 365 | | Stmt_Undefined _ 366 | | Stmt_ExceptionTaken _ 367 | | Stmt_See (_, _) 368 | | Stmt_Case (_, _, _, _) 369 | | Stmt_Dep_Unpred _ 370 | | Stmt_Dep_ImpDef (_, _) 371 | | Stmt_Dep_Undefined _ 372 | | Stmt_DecodeExecute (_, _, _) 373 | | Stmt_For (_, _, _, _, _, _) 374 | | Stmt_While (_, _, _) 375 | | Stmt_Repeat (_, _, _) 376 | | Stmt_Try (_, _, _, _, _) 377 | | Stmt_FunReturn (_, _) 378 | | Stmt_ProcReturn _ 379 | -> err "unsupported" 380 | 381 | 382 | and translate_stmts (stmts : stmt list) : llbasicblock * llbasicblock = 383 | match stmts with 384 | | [] -> 385 | let b = append_block ctx "end" func in b,b 386 | | s::rest -> 387 | let s' = translate_stmt s in 388 | let rest' = translate_stmts rest in 389 | link s' rest' 390 | 391 | 392 | let branchtaken_fix (build: llbuilder) : unit = 393 | let pc_ptr = Globals.find "PC" !vars in 394 | 395 | let branchtaken_ptr = Globals.find "__BranchTaken" !vars in 396 | let bt = build_load branchtaken_ptr "" build in 397 | let pc = build_load pc_ptr "" build in 398 | let inc = build_add pc (const_int (type_of pc) 4) "" build in 399 | let pc' = build_select bt pc inc "" build in 400 | ignore @@ build_store pc' pc_ptr build 401 | 402 | 403 | let translate_stmts_entry (stmts: stmt list) = 404 | vars := fold_left_globals (fun bs g -> Globals.add (value_name g) g bs) Globals.empty llmodule; 405 | 406 | let entry = append_block ctx "stmts_root" func in 407 | let entry_builder = builder_at_end ctx entry in 408 | 409 | let oldentry = entry_block func in 410 | delete_instruction (Option.get (block_terminator oldentry)) ; 411 | ignore @@ build_br entry (builder_at_end ctx oldentry); 412 | 413 | let branchtaken = build_alloca (i1_type ctx) "__BranchTaken" entry_builder in 414 | let locals = List.to_seq [ 415 | branchtaken; 416 | build_alloca (integer_type ctx 2) "BTypeNext" entry_builder; 417 | build_alloca bool_t "nRW" entry_builder; 418 | ] 419 | in 420 | vars := Globals.add_seq (Seq.map (fun x -> (value_name x, x)) locals) !vars; 421 | 422 | ignore @@ build_store bool_false branchtaken entry_builder; 423 | let (hd,tl) = translate_stmts stmts in 424 | 425 | ignore @@ build_br hd entry_builder; 426 | let tl_builder = builder_at_end ctx tl in 427 | branchtaken_fix tl_builder; 428 | ignore @@ build_ret_void tl_builder; 429 | 430 | 431 | hd,tl 432 | 433 | 434 | 435 | let load_aslb f = 436 | let chan = open_in_bin f in 437 | let stmts : LibASL.Asl_ast.stmt list = Marshal.from_channel chan in 438 | (* List.iter (fun x -> print_endline (LibASL.Asl_utils.pp_stmt x)) stmts *) 439 | stmts 440 | -------------------------------------------------------------------------------- /asl-translator/test/dune: -------------------------------------------------------------------------------- 1 | (test 2 | (name test)) 3 | -------------------------------------------------------------------------------- /asl-translator/test/test.ml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UQ-PAC/llvm-translator/2110ff718c2f3bd8f428653b3f6ce471eb399adb/asl-translator/test/test.ml -------------------------------------------------------------------------------- /in/adds.rem: -------------------------------------------------------------------------------- 1 | ; ModuleID = 'lifted_code' 2 | source_filename = "lifted_code" 3 | target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" 4 | target triple = "aarch64-pc-linux-gnu-elf" 5 | 6 | %struct.State = type { %struct.AArch64State } 7 | %struct.AArch64State = type { %struct.ArchState, %struct.SIMD, i64, %struct.GPR, i64, %union.anon, %union.anon, %union.anon, i64, %struct.SR, i64 } 8 | %struct.ArchState = type { i32, i32, %union.anon } 9 | %struct.SIMD = type { [32 x %union.vec128_t] } 10 | %union.vec128_t = type { %struct.uint128v1_t } 11 | %struct.uint128v1_t = type { [1 x i128] } 12 | %struct.GPR = type { i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg } 13 | %struct.Reg = type { %union.anon } 14 | %union.anon = type { i64 } 15 | %struct.SR = type { i64, %struct.Reg, i64, %struct.Reg, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, [6 x i8] } 16 | 17 | define ptr @sub_0(ptr noalias %state, i64 %program_counter, ptr noalias %memory) { 18 | %X3 = getelementptr inbounds %struct.State, ptr %state, i32 0, i32 0, i32 3, i32 7, i32 0, i32 0 19 | %X2 = getelementptr inbounds %struct.State, ptr %state, i32 0, i32 0, i32 3, i32 5, i32 0, i32 0 20 | %X1 = getelementptr inbounds %struct.State, ptr %state, i32 0, i32 0, i32 3, i32 3, i32 0, i32 0 21 | %BRANCH_TAKEN = alloca i8, align 4 22 | %RETURN_PC = alloca i64, align 8 23 | %MONITOR = alloca i64, align 8 24 | %STATE = alloca ptr, align 8 25 | store ptr %state, ptr %STATE, align 8 26 | %MEMORY = alloca ptr, align 8 27 | store ptr %memory, ptr %MEMORY, align 8 28 | %NEXT_PC = alloca i64, align 8 29 | store i64 %program_counter, ptr %NEXT_PC, align 8 30 | %WZR = alloca i32, align 4 31 | store i32 0, ptr %WZR, align 4 32 | %XZR = alloca i64, align 8 33 | store i64 0, ptr %XZR, align 8 34 | %IGNORE_WRITE_TO_WZR = alloca i32, align 4 35 | %IGNORE_WRITE_TO_XZR = alloca i64, align 8 36 | %SUPPRESS_WRITEBACK = alloca i64, align 8 37 | %PC = getelementptr inbounds %struct.State, ptr %state, i32 0, i32 0, i32 3, i32 65, i32 0, i32 0 38 | store i64 %program_counter, ptr %NEXT_PC, align 8 39 | br label %1 40 | 41 | 1: ; preds = %0 42 | %2 = load i64, ptr %NEXT_PC, align 8 43 | store i64 %2, ptr %PC, align 8 44 | %3 = add i64 %2, 4 45 | store i64 %3, ptr %NEXT_PC, align 8 46 | %4 = load i64, ptr %X2, align 8 47 | %5 = load i64, ptr %X3, align 8 48 | %6 = load ptr, ptr %MEMORY, align 8 49 | %L.sroa.0.0.insert.ext.i.i.i = zext i64 %4 to i128 50 | %R.sroa.0.0.insert.ext.i.i.i = zext i64 %5 to i128 51 | %L.sroa.0.0.insert.insert.i77.i.i = add nuw nsw i128 %R.sroa.0.0.insert.ext.i.i.i, %L.sroa.0.0.insert.ext.i.i.i 52 | %retval.sroa.0.0.extract.trunc.i78.i.i = trunc i128 %L.sroa.0.0.insert.insert.i77.i.i to i64 53 | %7 = ashr i64 %4, 63 54 | %8 = ashr i64 %5, 63 55 | %L.sroa.2.0.insert.ext.i87.i.i = zext i64 %7 to i128 56 | %R.sroa.2.0.insert.ext.i.i.i = zext i64 %8 to i128 57 | %reass.add.i = add nuw nsw i128 %R.sroa.2.0.insert.ext.i.i.i, %L.sroa.2.0.insert.ext.i87.i.i 58 | %reass.mul.i = shl i128 %reass.add.i, 64 59 | %L.sroa.0.0.insert.insert.i107.i.i = add i128 %reass.mul.i, %L.sroa.0.0.insert.insert.i77.i.i 60 | %cmp.i.i.i = icmp slt i64 %retval.sroa.0.0.extract.trunc.i78.i.i, 0 61 | %call1.i.i.i = call zeroext i1 (i1, ...) @__remill_flag_computation_sign(i1 noundef zeroext %cmp.i.i.i, i64 noundef %4, i64 noundef %5, i64 noundef %retval.sroa.0.0.extract.trunc.i78.i.i) #2 62 | %conv.i.i = zext i1 %call1.i.i.i to i8 63 | %n.i.i = getelementptr inbounds %struct.State, ptr %state, i64 0, i32 0, i32 9, i32 5 64 | store i8 %conv.i.i, ptr %n.i.i, align 1 65 | %cmp.i114.i.i = icmp eq i64 %retval.sroa.0.0.extract.trunc.i78.i.i, 0 66 | %call.i.i.i = call zeroext i1 (i1, ...) @__remill_flag_computation_zero(i1 noundef zeroext %cmp.i114.i.i, i64 noundef %4, i64 noundef %5, i64 noundef %retval.sroa.0.0.extract.trunc.i78.i.i) #2 67 | %conv34.i.i = zext i1 %call.i.i.i to i8 68 | %z.i.i = getelementptr inbounds %struct.State, ptr %state, i64 0, i32 0, i32 9, i32 7 69 | store i8 %conv34.i.i, ptr %z.i.i, align 1 70 | %L.sroa.0.0.insert.ext.i115.i.i = and i128 %L.sroa.0.0.insert.insert.i77.i.i, 18446744073709551615 71 | %9 = icmp ugt i128 %L.sroa.0.0.insert.insert.i77.i.i, 18446744073709551615 72 | %conv41.i.i = zext i1 %9 to i8 73 | %c.i.i = getelementptr inbounds %struct.State, ptr %state, i64 0, i32 0, i32 9, i32 9 74 | store i8 %conv41.i.i, ptr %c.i.i, align 1 75 | %10 = ashr i64 %retval.sroa.0.0.extract.trunc.i78.i.i, 63 76 | %L.sroa.2.0.insert.ext.i122.i.i = zext i64 %10 to i128 77 | %L.sroa.2.0.insert.shift.i123.i.i = shl nuw i128 %L.sroa.2.0.insert.ext.i122.i.i, 64 78 | %L.sroa.0.0.insert.insert.i125.i.i = or i128 %L.sroa.2.0.insert.shift.i123.i.i, %L.sroa.0.0.insert.ext.i115.i.i 79 | %cmp.i130.i.i = icmp ne i128 %L.sroa.0.0.insert.insert.i125.i.i, %L.sroa.0.0.insert.insert.i107.i.i 80 | %call48.i.i = call zeroext i1 (i1, ...) @__remill_flag_computation_overflow(i1 noundef zeroext %cmp.i130.i.i, i64 noundef %4, i64 noundef %5, i64 noundef %retval.sroa.0.0.extract.trunc.i78.i.i) #2 81 | %conv49.i.i = zext i1 %call48.i.i to i8 82 | %v.i.i = getelementptr inbounds %struct.State, ptr %state, i64 0, i32 0, i32 9, i32 11 83 | store i8 %conv49.i.i, ptr %v.i.i, align 1 84 | store i64 %retval.sroa.0.0.extract.trunc.i78.i.i, ptr %X1, align 8 85 | store ptr %6, ptr %MEMORY, align 8 86 | br label %11 87 | 88 | 11: ; preds = %1 89 | %12 = load i64, ptr %NEXT_PC, align 8 90 | store i64 %12, ptr %PC, align 8 91 | %13 = load ptr, ptr %MEMORY, align 8 92 | %14 = load i64, ptr %PC, align 8 93 | %15 = tail call ptr @__remill_missing_block(ptr %state, i64 %14, ptr %13) 94 | ret ptr %15 95 | } 96 | 97 | ; Function Attrs: mustprogress noduplicate nofree noinline nosync nounwind optnone readnone willreturn 98 | declare dso_local zeroext i1 @__remill_flag_computation_sign(i1 noundef zeroext, ...) #0 99 | 100 | ; Function Attrs: mustprogress noduplicate nofree noinline nosync nounwind optnone readnone willreturn 101 | declare dso_local zeroext i1 @__remill_flag_computation_zero(i1 noundef zeroext, ...) #0 102 | 103 | ; Function Attrs: mustprogress noduplicate nofree noinline nosync nounwind optnone readnone willreturn 104 | declare dso_local zeroext i1 @__remill_flag_computation_overflow(i1 noundef zeroext, ...) #0 105 | 106 | ; Function Attrs: noduplicate noinline nounwind optnone 107 | declare dso_local ptr @__remill_missing_block(ptr noundef nonnull align 1, i64 noundef, ptr noundef) #1 108 | 109 | attributes #0 = { mustprogress noduplicate nofree noinline nosync nounwind optnone readnone willreturn "frame-pointer"="none" "no-builtins" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "tune-cpu"="generic" } 110 | attributes #1 = { noduplicate noinline nounwind optnone "frame-pointer"="all" "no-builtins" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "tune-cpu"="generic" } 111 | attributes #2 = { nobuiltin nounwind readnone willreturn "no-builtins" } 112 | -------------------------------------------------------------------------------- /in/addv.rem: -------------------------------------------------------------------------------- 1 | ; ModuleID = 'lifted_code' 2 | source_filename = "lifted_code" 3 | target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" 4 | target triple = "aarch64-pc-linux-gnu-elf" 5 | 6 | %struct.State = type { %struct.AArch64State } 7 | %struct.AArch64State = type { %struct.ArchState, %struct.SIMD, i64, %struct.GPR, i64, %union.anon, %union.anon, %union.anon, i64, %struct.SR, i64 } 8 | %struct.ArchState = type { i32, i32, %union.anon } 9 | %struct.SIMD = type { [32 x %union.vec128_t] } 10 | %union.vec128_t = type { %struct.uint128v1_t } 11 | %struct.uint128v1_t = type { [1 x i128] } 12 | %struct.GPR = type { i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg } 13 | %struct.Reg = type { %union.anon } 14 | %union.anon = type { i64 } 15 | %struct.SR = type { i64, %struct.Reg, i64, %struct.Reg, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, [6 x i8] } 16 | 17 | define ptr @sub_0(ptr noalias %state, i64 %program_counter, ptr noalias %memory) { 18 | %Q2 = getelementptr inbounds %struct.State, ptr %state, i32 0, i32 0, i32 1, i32 0, i32 2, i32 0, i32 0, i32 0 19 | %Q1 = getelementptr inbounds %struct.State, ptr %state, i32 0, i32 0, i32 1, i32 0, i32 1, i32 0, i32 0, i32 0 20 | %V0 = getelementptr inbounds %struct.State, ptr %state, i32 0, i32 0, i32 1, i32 0, i32 0, i32 0, i32 0, i32 0 21 | %BRANCH_TAKEN = alloca i8, align 4 22 | %RETURN_PC = alloca i64, align 8 23 | %MONITOR = alloca i64, align 8 24 | %STATE = alloca ptr, align 8 25 | store ptr %state, ptr %STATE, align 8 26 | %MEMORY = alloca ptr, align 8 27 | store ptr %memory, ptr %MEMORY, align 8 28 | %NEXT_PC = alloca i64, align 8 29 | store i64 %program_counter, ptr %NEXT_PC, align 8 30 | %WZR = alloca i32, align 4 31 | store i32 0, ptr %WZR, align 4 32 | %XZR = alloca i64, align 8 33 | store i64 0, ptr %XZR, align 8 34 | %IGNORE_WRITE_TO_WZR = alloca i32, align 4 35 | %IGNORE_WRITE_TO_XZR = alloca i64, align 8 36 | %SUPPRESS_WRITEBACK = alloca i64, align 8 37 | %PC = getelementptr inbounds %struct.State, ptr %state, i32 0, i32 0, i32 3, i32 65, i32 0, i32 0 38 | store i64 %program_counter, ptr %NEXT_PC, align 8 39 | br label %1 40 | 41 | 1: ; preds = %0 42 | %2 = load i64, ptr %NEXT_PC, align 8 43 | store i64 %2, ptr %PC, align 8 44 | %3 = add i64 %2, 4 45 | store i64 %3, ptr %NEXT_PC, align 8 46 | %4 = load ptr, ptr %MEMORY, align 8 47 | %retval.sroa.0.0.copyload.i.i = load i64, ptr %Q1, align 1 48 | %retval.sroa.2.0..sroa_idx.i.i = getelementptr inbounds i8, ptr %Q1, i64 8 49 | %retval.sroa.2.0.copyload.i.i = load i64, ptr %retval.sroa.2.0..sroa_idx.i.i, align 1 50 | %vec1.sroa.0.sroa.0.0.extract.trunc.i = trunc i64 %retval.sroa.0.0.copyload.i.i to i32 51 | %vec1.sroa.0.sroa.4.0.extract.shift.i = lshr i64 %retval.sroa.0.0.copyload.i.i, 32 52 | %vec1.sroa.0.sroa.4.0.extract.trunc.i = trunc i64 %vec1.sroa.0.sroa.4.0.extract.shift.i to i32 53 | %retval.sroa.0.0.copyload.i26.i = load i64, ptr %Q2, align 1 54 | %retval.sroa.2.0..sroa_idx.i27.i = getelementptr inbounds i8, ptr %Q2, i64 8 55 | %retval.sroa.2.0.copyload.i29.i = load i64, ptr %retval.sroa.2.0..sroa_idx.i27.i, align 1 56 | %vec2.sroa.0.sroa.0.0.extract.trunc.i = trunc i64 %retval.sroa.0.0.copyload.i26.i to i32 57 | %vec2.sroa.0.sroa.4.0.extract.shift.i = lshr i64 %retval.sroa.0.0.copyload.i26.i, 32 58 | %vec2.sroa.0.sroa.4.0.extract.trunc.i = trunc i64 %vec2.sroa.0.sroa.4.0.extract.shift.i to i32 59 | %add.i.i = add i32 %vec2.sroa.0.sroa.0.0.extract.trunc.i, %vec1.sroa.0.sroa.0.0.extract.trunc.i 60 | %add.i.1.i = add i32 %vec2.sroa.0.sroa.4.0.extract.trunc.i, %vec1.sroa.0.sroa.4.0.extract.trunc.i 61 | %vec1.sroa.5.8.extract.trunc.i = trunc i64 %retval.sroa.2.0.copyload.i.i to i32 62 | %vec2.sroa.5.8.extract.trunc.i = trunc i64 %retval.sroa.2.0.copyload.i29.i to i32 63 | %add.i.2.i = add i32 %vec2.sroa.5.8.extract.trunc.i, %vec1.sroa.5.8.extract.trunc.i 64 | %vec1.sroa.5.12.extract.shift.i = lshr i64 %retval.sroa.2.0.copyload.i.i, 32 65 | %vec1.sroa.5.12.extract.trunc.i = trunc i64 %vec1.sroa.5.12.extract.shift.i to i32 66 | %vec2.sroa.5.12.extract.shift.i = lshr i64 %retval.sroa.2.0.copyload.i29.i, 32 67 | %vec2.sroa.5.12.extract.trunc.i = trunc i64 %vec2.sroa.5.12.extract.shift.i to i32 68 | %add.i.3.i = add i32 %vec2.sroa.5.12.extract.trunc.i, %vec1.sroa.5.12.extract.trunc.i 69 | store i32 %add.i.i, ptr %V0, align 1 70 | %arrayidx2.1.i.i = getelementptr inbounds i8, ptr %V0, i64 4 71 | store i32 %add.i.1.i, ptr %arrayidx2.1.i.i, align 1 72 | %arrayidx2.2.i.i = getelementptr inbounds i8, ptr %V0, i64 8 73 | store i32 %add.i.2.i, ptr %arrayidx2.2.i.i, align 1 74 | %arrayidx2.3.i.i = getelementptr inbounds i8, ptr %V0, i64 12 75 | store i32 %add.i.3.i, ptr %arrayidx2.3.i.i, align 1 76 | store ptr %4, ptr %MEMORY, align 8 77 | br label %5 78 | 79 | 5: ; preds = %1 80 | %6 = load i64, ptr %NEXT_PC, align 8 81 | store i64 %6, ptr %PC, align 8 82 | %7 = load ptr, ptr %MEMORY, align 8 83 | %8 = load i64, ptr %PC, align 8 84 | %9 = tail call ptr @__remill_missing_block(ptr %state, i64 %8, ptr %7) 85 | ret ptr %9 86 | } 87 | 88 | ; Function Attrs: noduplicate noinline nounwind optnone 89 | declare dso_local ptr @__remill_missing_block(ptr noundef nonnull align 1, i64 noundef, ptr noundef) #0 90 | 91 | attributes #0 = { noduplicate noinline nounwind optnone "frame-pointer"="all" "no-builtins" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "tune-cpu"="generic" } 92 | -------------------------------------------------------------------------------- /in/ldr.rem: -------------------------------------------------------------------------------- 1 | ; ModuleID = 'lifted_code' 2 | source_filename = "lifted_code" 3 | target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" 4 | target triple = "aarch64-pc-linux-gnu-elf" 5 | 6 | %struct.State = type { %struct.AArch64State } 7 | %struct.AArch64State = type { %struct.ArchState, %struct.SIMD, i64, %struct.GPR, i64, %union.anon, %union.anon, %union.anon, i64, %struct.SR, i64 } 8 | %struct.ArchState = type { i32, i32, %union.anon } 9 | %struct.SIMD = type { [32 x %union.vec128_t] } 10 | %union.vec128_t = type { %struct.uint128v1_t } 11 | %struct.uint128v1_t = type { [1 x i128] } 12 | %struct.GPR = type { i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg } 13 | %struct.Reg = type { %union.anon } 14 | %union.anon = type { i64 } 15 | %struct.SR = type { i64, %struct.Reg, i64, %struct.Reg, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, [6 x i8] } 16 | 17 | define ptr @sub_0(ptr noalias %state, i64 %program_counter, ptr noalias %memory) { 18 | %X3 = getelementptr inbounds %struct.State, ptr %state, i32 0, i32 0, i32 3, i32 7, i32 0, i32 0 19 | %X2 = getelementptr inbounds %struct.State, ptr %state, i32 0, i32 0, i32 3, i32 5, i32 0, i32 0 20 | %X1 = getelementptr inbounds %struct.State, ptr %state, i32 0, i32 0, i32 3, i32 3, i32 0, i32 0 21 | %BRANCH_TAKEN = alloca i8, align 4 22 | %RETURN_PC = alloca i64, align 8 23 | %MONITOR = alloca i64, align 8 24 | %STATE = alloca ptr, align 8 25 | store ptr %state, ptr %STATE, align 8 26 | %MEMORY = alloca ptr, align 8 27 | store ptr %memory, ptr %MEMORY, align 8 28 | %NEXT_PC = alloca i64, align 8 29 | store i64 %program_counter, ptr %NEXT_PC, align 8 30 | %WZR = alloca i32, align 4 31 | store i32 0, ptr %WZR, align 4 32 | %XZR = alloca i64, align 8 33 | store i64 0, ptr %XZR, align 8 34 | %IGNORE_WRITE_TO_WZR = alloca i32, align 4 35 | %IGNORE_WRITE_TO_XZR = alloca i64, align 8 36 | %SUPPRESS_WRITEBACK = alloca i64, align 8 37 | %PC = getelementptr inbounds %struct.State, ptr %state, i32 0, i32 0, i32 3, i32 65, i32 0, i32 0 38 | store i64 %program_counter, ptr %NEXT_PC, align 8 39 | br label %1 40 | 41 | 1: ; preds = %0 42 | %2 = load i64, ptr %NEXT_PC, align 8 43 | store i64 %2, ptr %PC, align 8 44 | %3 = add i64 %2, 4 45 | store i64 %3, ptr %NEXT_PC, align 8 46 | %4 = load i64, ptr %X2, align 8 47 | %5 = load i64, ptr %X3, align 8 48 | %6 = load ptr, ptr %MEMORY, align 8 49 | %add.i.i = add i64 %5, %4 50 | %call.i.i = call i64 @__remill_read_memory_64(ptr noundef %6, i64 noundef %add.i.i) #2 51 | store i64 %call.i.i, ptr %X1, align 8 52 | store ptr %6, ptr %MEMORY, align 8 53 | br label %7 54 | 55 | 7: ; preds = %1 56 | %8 = load i64, ptr %NEXT_PC, align 8 57 | store i64 %8, ptr %PC, align 8 58 | %9 = load ptr, ptr %MEMORY, align 8 59 | %10 = load i64, ptr %PC, align 8 60 | %11 = tail call ptr @__remill_missing_block(ptr %state, i64 %10, ptr %9) 61 | ret ptr %11 62 | } 63 | 64 | ; Function Attrs: mustprogress noduplicate nofree noinline nosync nounwind optnone readnone willreturn 65 | declare dso_local i64 @__remill_read_memory_64(ptr noundef readnone, i64 noundef) #0 66 | 67 | ; Function Attrs: noduplicate noinline nounwind optnone 68 | declare dso_local ptr @__remill_missing_block(ptr noundef nonnull align 1, i64 noundef, ptr noundef) #1 69 | 70 | attributes #0 = { mustprogress noduplicate nofree noinline nosync nounwind optnone readnone willreturn "frame-pointer"="none" "no-builtins" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "tune-cpu"="generic" } 71 | attributes #1 = { noduplicate noinline nounwind optnone "frame-pointer"="all" "no-builtins" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "tune-cpu"="generic" } 72 | attributes #2 = { nobuiltin nounwind readnone willreturn "no-builtins" } 73 | -------------------------------------------------------------------------------- /in/ret.cap: -------------------------------------------------------------------------------- 1 | ; ModuleID = 'test' 2 | source_filename = "test" 3 | target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128" 4 | 5 | @capstone_asm2llvm = internal global i64 0 6 | @v0 = internal global i128 0 7 | @v1 = internal global i128 0 8 | @v2 = internal global i128 0 9 | @v3 = internal global i128 0 10 | @v4 = internal global i128 0 11 | @v5 = internal global i128 0 12 | @v6 = internal global i128 0 13 | @v7 = internal global i128 0 14 | @v8 = internal global i128 0 15 | @v9 = internal global i128 0 16 | @v10 = internal global i128 0 17 | @v11 = internal global i128 0 18 | @v12 = internal global i128 0 19 | @v13 = internal global i128 0 20 | @v14 = internal global i128 0 21 | @v15 = internal global i128 0 22 | @v16 = internal global i128 0 23 | @v17 = internal global i128 0 24 | @v18 = internal global i128 0 25 | @v19 = internal global i128 0 26 | @v20 = internal global i128 0 27 | @v21 = internal global i128 0 28 | @v22 = internal global i128 0 29 | @v23 = internal global i128 0 30 | @v24 = internal global i128 0 31 | @v25 = internal global i128 0 32 | @v26 = internal global i128 0 33 | @v27 = internal global i128 0 34 | @v28 = internal global i128 0 35 | @v29 = internal global i128 0 36 | @v30 = internal global i128 0 37 | @v31 = internal global i128 0 38 | @q0 = internal global fp128 0xL00000000000000000000000000000000 39 | @q1 = internal global fp128 0xL00000000000000000000000000000000 40 | @q2 = internal global fp128 0xL00000000000000000000000000000000 41 | @q3 = internal global fp128 0xL00000000000000000000000000000000 42 | @q4 = internal global fp128 0xL00000000000000000000000000000000 43 | @q5 = internal global fp128 0xL00000000000000000000000000000000 44 | @q6 = internal global fp128 0xL00000000000000000000000000000000 45 | @q7 = internal global fp128 0xL00000000000000000000000000000000 46 | @q8 = internal global fp128 0xL00000000000000000000000000000000 47 | @q9 = internal global fp128 0xL00000000000000000000000000000000 48 | @q10 = internal global fp128 0xL00000000000000000000000000000000 49 | @q11 = internal global fp128 0xL00000000000000000000000000000000 50 | @q12 = internal global fp128 0xL00000000000000000000000000000000 51 | @q13 = internal global fp128 0xL00000000000000000000000000000000 52 | @q14 = internal global fp128 0xL00000000000000000000000000000000 53 | @q15 = internal global fp128 0xL00000000000000000000000000000000 54 | @q16 = internal global fp128 0xL00000000000000000000000000000000 55 | @q17 = internal global fp128 0xL00000000000000000000000000000000 56 | @q18 = internal global fp128 0xL00000000000000000000000000000000 57 | @q19 = internal global fp128 0xL00000000000000000000000000000000 58 | @q20 = internal global fp128 0xL00000000000000000000000000000000 59 | @q21 = internal global fp128 0xL00000000000000000000000000000000 60 | @q22 = internal global fp128 0xL00000000000000000000000000000000 61 | @q23 = internal global fp128 0xL00000000000000000000000000000000 62 | @q24 = internal global fp128 0xL00000000000000000000000000000000 63 | @q25 = internal global fp128 0xL00000000000000000000000000000000 64 | @q26 = internal global fp128 0xL00000000000000000000000000000000 65 | @q27 = internal global fp128 0xL00000000000000000000000000000000 66 | @q28 = internal global fp128 0xL00000000000000000000000000000000 67 | @q29 = internal global fp128 0xL00000000000000000000000000000000 68 | @q30 = internal global fp128 0xL00000000000000000000000000000000 69 | @q31 = internal global fp128 0xL00000000000000000000000000000000 70 | @d0 = internal global double 0.000000e+00 71 | @d1 = internal global double 0.000000e+00 72 | @d2 = internal global double 0.000000e+00 73 | @d3 = internal global double 0.000000e+00 74 | @d4 = internal global double 0.000000e+00 75 | @d5 = internal global double 0.000000e+00 76 | @d6 = internal global double 0.000000e+00 77 | @d7 = internal global double 0.000000e+00 78 | @d8 = internal global double 0.000000e+00 79 | @d9 = internal global double 0.000000e+00 80 | @d10 = internal global double 0.000000e+00 81 | @d11 = internal global double 0.000000e+00 82 | @d12 = internal global double 0.000000e+00 83 | @d13 = internal global double 0.000000e+00 84 | @d14 = internal global double 0.000000e+00 85 | @d15 = internal global double 0.000000e+00 86 | @d16 = internal global double 0.000000e+00 87 | @d17 = internal global double 0.000000e+00 88 | @d18 = internal global double 0.000000e+00 89 | @d19 = internal global double 0.000000e+00 90 | @d20 = internal global double 0.000000e+00 91 | @d21 = internal global double 0.000000e+00 92 | @d22 = internal global double 0.000000e+00 93 | @d23 = internal global double 0.000000e+00 94 | @d24 = internal global double 0.000000e+00 95 | @d25 = internal global double 0.000000e+00 96 | @d26 = internal global double 0.000000e+00 97 | @d27 = internal global double 0.000000e+00 98 | @d28 = internal global double 0.000000e+00 99 | @d29 = internal global double 0.000000e+00 100 | @d30 = internal global double 0.000000e+00 101 | @d31 = internal global double 0.000000e+00 102 | @s0 = internal global float 0.000000e+00 103 | @s1 = internal global float 0.000000e+00 104 | @s2 = internal global float 0.000000e+00 105 | @s3 = internal global float 0.000000e+00 106 | @s4 = internal global float 0.000000e+00 107 | @s5 = internal global float 0.000000e+00 108 | @s6 = internal global float 0.000000e+00 109 | @s7 = internal global float 0.000000e+00 110 | @s8 = internal global float 0.000000e+00 111 | @s9 = internal global float 0.000000e+00 112 | @s10 = internal global float 0.000000e+00 113 | @s11 = internal global float 0.000000e+00 114 | @s12 = internal global float 0.000000e+00 115 | @s13 = internal global float 0.000000e+00 116 | @s14 = internal global float 0.000000e+00 117 | @s15 = internal global float 0.000000e+00 118 | @s16 = internal global float 0.000000e+00 119 | @s17 = internal global float 0.000000e+00 120 | @s18 = internal global float 0.000000e+00 121 | @s19 = internal global float 0.000000e+00 122 | @s20 = internal global float 0.000000e+00 123 | @s21 = internal global float 0.000000e+00 124 | @s22 = internal global float 0.000000e+00 125 | @s23 = internal global float 0.000000e+00 126 | @s24 = internal global float 0.000000e+00 127 | @s25 = internal global float 0.000000e+00 128 | @s26 = internal global float 0.000000e+00 129 | @s27 = internal global float 0.000000e+00 130 | @s28 = internal global float 0.000000e+00 131 | @s29 = internal global float 0.000000e+00 132 | @s30 = internal global float 0.000000e+00 133 | @s31 = internal global float 0.000000e+00 134 | @h0 = internal global i16 0 135 | @h1 = internal global i16 0 136 | @h2 = internal global i16 0 137 | @h3 = internal global i16 0 138 | @h4 = internal global i16 0 139 | @h5 = internal global i16 0 140 | @h6 = internal global i16 0 141 | @h7 = internal global i16 0 142 | @h8 = internal global i16 0 143 | @h9 = internal global i16 0 144 | @h10 = internal global i16 0 145 | @h11 = internal global i16 0 146 | @h12 = internal global i16 0 147 | @h13 = internal global i16 0 148 | @h14 = internal global i16 0 149 | @h15 = internal global i16 0 150 | @h16 = internal global i16 0 151 | @h17 = internal global i16 0 152 | @h18 = internal global i16 0 153 | @h19 = internal global i16 0 154 | @h20 = internal global i16 0 155 | @h21 = internal global i16 0 156 | @h22 = internal global i16 0 157 | @h23 = internal global i16 0 158 | @h24 = internal global i16 0 159 | @h25 = internal global i16 0 160 | @h26 = internal global i16 0 161 | @h27 = internal global i16 0 162 | @h28 = internal global i16 0 163 | @h29 = internal global i16 0 164 | @h30 = internal global i16 0 165 | @h31 = internal global i16 0 166 | @b0 = internal global i8 0 167 | @b1 = internal global i8 0 168 | @b2 = internal global i8 0 169 | @b3 = internal global i8 0 170 | @b4 = internal global i8 0 171 | @b5 = internal global i8 0 172 | @b6 = internal global i8 0 173 | @b7 = internal global i8 0 174 | @b8 = internal global i8 0 175 | @b9 = internal global i8 0 176 | @b10 = internal global i8 0 177 | @b11 = internal global i8 0 178 | @b12 = internal global i8 0 179 | @b13 = internal global i8 0 180 | @b14 = internal global i8 0 181 | @b15 = internal global i8 0 182 | @b16 = internal global i8 0 183 | @b17 = internal global i8 0 184 | @b18 = internal global i8 0 185 | @b19 = internal global i8 0 186 | @b20 = internal global i8 0 187 | @b21 = internal global i8 0 188 | @daifset = internal global i8 0 189 | @daifclr = internal global i8 0 190 | @b24 = internal global i8 0 191 | @b25 = internal global i8 0 192 | @b26 = internal global i8 0 193 | @b27 = internal global i8 0 194 | @b28 = internal global i8 0 195 | @b29 = internal global i8 0 196 | @b30 = internal global i8 0 197 | @b31 = internal global i8 0 198 | @x0 = internal global i64 0 199 | @x1 = internal global i64 0 200 | @x2 = internal global i64 0 201 | @x3 = internal global i64 0 202 | @x4 = internal global i64 0 203 | @x5 = internal global i64 0 204 | @x6 = internal global i64 0 205 | @x7 = internal global i64 0 206 | @x8 = internal global i64 0 207 | @x9 = internal global i64 0 208 | @x10 = internal global i64 0 209 | @x11 = internal global i64 0 210 | @x12 = internal global i64 0 211 | @x13 = internal global i64 0 212 | @x14 = internal global i64 0 213 | @x15 = internal global i64 0 214 | @x16 = internal global i64 0 215 | @x17 = internal global i64 0 216 | @x18 = internal global i64 0 217 | @x19 = internal global i64 0 218 | @x20 = internal global i64 0 219 | @x21 = internal global i64 0 220 | @x22 = internal global i64 0 221 | @x23 = internal global i64 0 222 | @x24 = internal global i64 0 223 | @x25 = internal global i64 0 224 | @x26 = internal global i64 0 225 | @x27 = internal global i64 0 226 | @x28 = internal global i64 0 227 | @x29 = internal global i64 0 228 | @x30 = internal global i64 0 229 | @sp = internal global i64 0 230 | @spsel = internal global i32 0 231 | @daifset.1 = internal global i8 0 232 | @daifclr.2 = internal global i8 0 233 | @cpsr_n = internal global i1 false 234 | @cpsr_z = internal global i1 false 235 | @cpsr_c = internal global i1 false 236 | @cpsr_v = internal global i1 false 237 | @pc = internal global i64 0 238 | @osdtrrx_el1 = internal global i64 0 239 | @dbgbvr0_el1 = internal global i64 0 240 | @dbgbcr0_el1 = internal global i64 0 241 | @dbgwvr0_el1 = internal global i64 0 242 | @dbgwcr0_el1 = internal global i64 0 243 | @dbgbvr1_el1 = internal global i64 0 244 | @dbgbcr1_el1 = internal global i64 0 245 | @dbgwvr1_el1 = internal global i64 0 246 | @dbgwcr1_el1 = internal global i64 0 247 | @mdccint_el1 = internal global i64 0 248 | @mdscr_el1 = internal global i64 0 249 | @dbgbvr2_el1 = internal global i64 0 250 | @dbgbcr2_el1 = internal global i64 0 251 | @dbgwvr2_el1 = internal global i64 0 252 | @dbgwcr2_el1 = internal global i64 0 253 | @osdtrtx_el1 = internal global i64 0 254 | @dbgbvr3_el1 = internal global i64 0 255 | @dbgbcr3_el1 = internal global i64 0 256 | @dbgwvr3_el1 = internal global i64 0 257 | @dbgwcr3_el1 = internal global i64 0 258 | @dbgbvr4_el1 = internal global i64 0 259 | @dbgbcr4_el1 = internal global i64 0 260 | @dbgwvr4_el1 = internal global i64 0 261 | @dbgwcr4_el1 = internal global i64 0 262 | @dbgbvr5_el1 = internal global i64 0 263 | @dbgbcr5_el1 = internal global i64 0 264 | @dbgwvr5_el1 = internal global i64 0 265 | @dbgwcr5_el1 = internal global i64 0 266 | @oseccr_el1 = internal global i64 0 267 | @dbgbvr6_el1 = internal global i64 0 268 | @dbgbcr6_el1 = internal global i64 0 269 | @dbgwvr6_el1 = internal global i64 0 270 | @dbgwcr6_el1 = internal global i64 0 271 | @dbgbvr7_el1 = internal global i64 0 272 | @dbgbcr7_el1 = internal global i64 0 273 | @dbgwvr7_el1 = internal global i64 0 274 | @dbgwcr7_el1 = internal global i64 0 275 | @dbgbvr8_el1 = internal global i64 0 276 | @dbgbcr8_el1 = internal global i64 0 277 | @dbgwvr8_el1 = internal global i64 0 278 | @dbgwcr8_el1 = internal global i64 0 279 | @dbgbvr9_el1 = internal global i64 0 280 | @dbgbcr9_el1 = internal global i64 0 281 | @dbgwvr9_el1 = internal global i64 0 282 | @dbgwcr9_el1 = internal global i64 0 283 | @dbgbvr10_el1 = internal global i64 0 284 | @dbgbcr10_el1 = internal global i64 0 285 | @dbgwvr10_el1 = internal global i64 0 286 | @dbgwcr10_el1 = internal global i64 0 287 | @dbgbvr11_el1 = internal global i64 0 288 | @dbgbcr11_el1 = internal global i64 0 289 | @dbgwvr11_el1 = internal global i64 0 290 | @dbgwcr11_el1 = internal global i64 0 291 | @dbgbvr12_el1 = internal global i64 0 292 | @dbgbcr12_el1 = internal global i64 0 293 | @dbgwvr12_el1 = internal global i64 0 294 | @dbgwcr12_el1 = internal global i64 0 295 | @dbgbvr13_el1 = internal global i64 0 296 | @dbgbcr13_el1 = internal global i64 0 297 | @dbgwvr13_el1 = internal global i64 0 298 | @dbgwcr13_el1 = internal global i64 0 299 | @dbgbvr14_el1 = internal global i64 0 300 | @dbgbcr14_el1 = internal global i64 0 301 | @dbgwvr14_el1 = internal global i64 0 302 | @dbgwcr14_el1 = internal global i64 0 303 | @dbgbvr15_el1 = internal global i64 0 304 | @dbgbcr15_el1 = internal global i64 0 305 | @dbgwvr15_el1 = internal global i64 0 306 | @dbgwcr15_el1 = internal global i64 0 307 | @mdrar_el1 = internal global i64 0 308 | @oslsr_el1 = internal global i64 0 309 | @osdlr_el1 = internal global i64 0 310 | @dbgprcr_el1 = internal global i64 0 311 | @dbgclaimset_el1 = internal global i64 0 312 | @dbgclaimclr_el1 = internal global i64 0 313 | @dbgauthstatus_el1 = internal global i64 0 314 | @trctraceidr = internal global i64 0 315 | @trcvictlr = internal global i64 0 316 | @trcseqevr0 = internal global i64 0 317 | @trccntrldvr0 = internal global i64 0 318 | @trcidr8 = internal global i64 0 319 | @trcimspec0 = internal global i64 0 320 | @trcprgctlr = internal global i64 0 321 | @trcqctlr = internal global i64 0 322 | @trcviiectlr = internal global i64 0 323 | @trcseqevr1 = internal global i64 0 324 | @trccntrldvr1 = internal global i64 0 325 | @trcidr9 = internal global i64 0 326 | @trcimspec1 = internal global i64 0 327 | @trcprocselr = internal global i64 0 328 | @trcvissctlr = internal global i64 0 329 | @trcseqevr2 = internal global i64 0 330 | @trccntrldvr2 = internal global i64 0 331 | @trcidr10 = internal global i64 0 332 | @trcimspec2 = internal global i64 0 333 | @trcstatr = internal global i64 0 334 | @trcvipcssctlr = internal global i64 0 335 | @trccntrldvr3 = internal global i64 0 336 | @trcidr11 = internal global i64 0 337 | @trcimspec3 = internal global i64 0 338 | @trcconfigr = internal global i64 0 339 | @trccntctlr0 = internal global i64 0 340 | @trcidr12 = internal global i64 0 341 | @trcimspec4 = internal global i64 0 342 | @trccntctlr1 = internal global i64 0 343 | @trcidr13 = internal global i64 0 344 | @trcimspec5 = internal global i64 0 345 | @trcauxctlr = internal global i64 0 346 | @trcseqrstevr = internal global i64 0 347 | @trccntctlr2 = internal global i64 0 348 | @trcimspec6 = internal global i64 0 349 | @trcseqstr = internal global i64 0 350 | @trccntctlr3 = internal global i64 0 351 | @trcimspec7 = internal global i64 0 352 | @trceventctl0r = internal global i64 0 353 | @trcvdctlr = internal global i64 0 354 | @trcextinselr = internal global i64 0 355 | @trccntvr0 = internal global i64 0 356 | @trcidr0 = internal global i64 0 357 | @trceventctl1r = internal global i64 0 358 | @trcvdsacctlr = internal global i64 0 359 | @trccntvr1 = internal global i64 0 360 | @trcidr1 = internal global i64 0 361 | @trcvdarcctlr = internal global i64 0 362 | @trccntvr2 = internal global i64 0 363 | @trcidr2 = internal global i64 0 364 | @trcstallctlr = internal global i64 0 365 | @trccntvr3 = internal global i64 0 366 | @trcidr3 = internal global i64 0 367 | @trctsctlr = internal global i64 0 368 | @trcidr4 = internal global i64 0 369 | @trcsyncpr = internal global i64 0 370 | @trcidr5 = internal global i64 0 371 | @trcccctlr = internal global i64 0 372 | @trcidr6 = internal global i64 0 373 | @trcbbctlr = internal global i64 0 374 | @trcidr7 = internal global i64 0 375 | @trcrsctlr16 = internal global i64 0 376 | @trcssccr0 = internal global i64 0 377 | @trcsspcicr0 = internal global i64 0 378 | @trcrsctlr17 = internal global i64 0 379 | @trcssccr1 = internal global i64 0 380 | @trcsspcicr1 = internal global i64 0 381 | @trcoslsr = internal global i64 0 382 | @trcrsctlr2 = internal global i64 0 383 | @trcrsctlr18 = internal global i64 0 384 | @trcssccr2 = internal global i64 0 385 | @trcsspcicr2 = internal global i64 0 386 | @trcrsctlr3 = internal global i64 0 387 | @trcrsctlr19 = internal global i64 0 388 | @trcssccr3 = internal global i64 0 389 | @trcsspcicr3 = internal global i64 0 390 | @trcrsctlr4 = internal global i64 0 391 | @trcrsctlr20 = internal global i64 0 392 | @trcssccr4 = internal global i64 0 393 | @trcsspcicr4 = internal global i64 0 394 | @trcpdcr = internal global i64 0 395 | @trcrsctlr5 = internal global i64 0 396 | @trcrsctlr21 = internal global i64 0 397 | @trcssccr5 = internal global i64 0 398 | @trcsspcicr5 = internal global i64 0 399 | @trcpdsr = internal global i64 0 400 | @trcrsctlr6 = internal global i64 0 401 | @trcrsctlr22 = internal global i64 0 402 | @trcssccr6 = internal global i64 0 403 | @trcsspcicr6 = internal global i64 0 404 | @trcrsctlr7 = internal global i64 0 405 | @trcrsctlr23 = internal global i64 0 406 | @trcssccr7 = internal global i64 0 407 | @trcsspcicr7 = internal global i64 0 408 | @trcrsctlr8 = internal global i64 0 409 | @trcrsctlr24 = internal global i64 0 410 | @trcsscsr0 = internal global i64 0 411 | @trcrsctlr9 = internal global i64 0 412 | @trcrsctlr25 = internal global i64 0 413 | @trcsscsr1 = internal global i64 0 414 | @trcrsctlr10 = internal global i64 0 415 | @trcrsctlr26 = internal global i64 0 416 | @trcsscsr2 = internal global i64 0 417 | @trcrsctlr11 = internal global i64 0 418 | @trcrsctlr27 = internal global i64 0 419 | @trcsscsr3 = internal global i64 0 420 | @trcrsctlr12 = internal global i64 0 421 | @trcrsctlr28 = internal global i64 0 422 | @trcsscsr4 = internal global i64 0 423 | @trcrsctlr13 = internal global i64 0 424 | @trcrsctlr29 = internal global i64 0 425 | @trcsscsr5 = internal global i64 0 426 | @trcrsctlr14 = internal global i64 0 427 | @trcrsctlr30 = internal global i64 0 428 | @trcsscsr6 = internal global i64 0 429 | @trcrsctlr15 = internal global i64 0 430 | @trcrsctlr31 = internal global i64 0 431 | @trcsscsr7 = internal global i64 0 432 | @trcacvr0 = internal global i64 0 433 | @trcacvr8 = internal global i64 0 434 | @trcacatr0 = internal global i64 0 435 | @trcacatr8 = internal global i64 0 436 | @trcdvcvr0 = internal global i64 0 437 | @trcdvcvr4 = internal global i64 0 438 | @trcdvcmr0 = internal global i64 0 439 | @trcdvcmr4 = internal global i64 0 440 | @trcacvr1 = internal global i64 0 441 | @trcacvr9 = internal global i64 0 442 | @trcacatr1 = internal global i64 0 443 | @trcacatr9 = internal global i64 0 444 | @trcacvr2 = internal global i64 0 445 | @trcacvr10 = internal global i64 0 446 | @trcacatr2 = internal global i64 0 447 | @trcacatr10 = internal global i64 0 448 | @trcdvcvr1 = internal global i64 0 449 | @trcdvcvr5 = internal global i64 0 450 | @trcdvcmr1 = internal global i64 0 451 | @trcdvcmr5 = internal global i64 0 452 | @trcacvr3 = internal global i64 0 453 | @trcacvr11 = internal global i64 0 454 | @trcacatr3 = internal global i64 0 455 | @trcacatr11 = internal global i64 0 456 | @trcacvr4 = internal global i64 0 457 | @trcacvr12 = internal global i64 0 458 | @trcacatr4 = internal global i64 0 459 | @trcacatr12 = internal global i64 0 460 | @trcdvcvr2 = internal global i64 0 461 | @trcdvcvr6 = internal global i64 0 462 | @trcdvcmr2 = internal global i64 0 463 | @trcdvcmr6 = internal global i64 0 464 | @trcacvr5 = internal global i64 0 465 | @trcacvr13 = internal global i64 0 466 | @trcacatr5 = internal global i64 0 467 | @trcacatr13 = internal global i64 0 468 | @trcacvr6 = internal global i64 0 469 | @trcacvr14 = internal global i64 0 470 | @trcacatr6 = internal global i64 0 471 | @trcacatr14 = internal global i64 0 472 | @trcdvcvr3 = internal global i64 0 473 | @trcdvcvr7 = internal global i64 0 474 | @trcdvcmr3 = internal global i64 0 475 | @trcdvcmr7 = internal global i64 0 476 | @trcacvr7 = internal global i64 0 477 | @trcacvr15 = internal global i64 0 478 | @trcacatr7 = internal global i64 0 479 | @trcacatr15 = internal global i64 0 480 | @trccidcvr0 = internal global i64 0 481 | @trcvmidcvr0 = internal global i64 0 482 | @trccidcctlr0 = internal global i64 0 483 | @trccidcctlr1 = internal global i64 0 484 | @trccidcvr1 = internal global i64 0 485 | @trcvmidcvr1 = internal global i64 0 486 | @trcvmidcctlr0 = internal global i64 0 487 | @trcvmidcctlr1 = internal global i64 0 488 | @trccidcvr2 = internal global i64 0 489 | @trcvmidcvr2 = internal global i64 0 490 | @trccidcvr3 = internal global i64 0 491 | @trcvmidcvr3 = internal global i64 0 492 | @trccidcvr4 = internal global i64 0 493 | @trcvmidcvr4 = internal global i64 0 494 | @trccidcvr5 = internal global i64 0 495 | @trcvmidcvr5 = internal global i64 0 496 | @trccidcvr6 = internal global i64 0 497 | @trcvmidcvr6 = internal global i64 0 498 | @trccidcvr7 = internal global i64 0 499 | @trcvmidcvr7 = internal global i64 0 500 | @trcitctrl = internal global i64 0 501 | @trcdevid = internal global i64 0 502 | @trcdevtype = internal global i64 0 503 | @trcpidr4 = internal global i64 0 504 | @trcpidr5 = internal global i64 0 505 | @trcpidr6 = internal global i64 0 506 | @trcpidr7 = internal global i64 0 507 | @trcclaimset = internal global i64 0 508 | @trcpidr0 = internal global i64 0 509 | @trcclaimclr = internal global i64 0 510 | @trcpidr1 = internal global i64 0 511 | @trcdevaff0 = internal global i64 0 512 | @trcpidr2 = internal global i64 0 513 | @trcdevaff1 = internal global i64 0 514 | @trcpidr3 = internal global i64 0 515 | @trccidr0 = internal global i64 0 516 | @trclsr = internal global i64 0 517 | @trccidr1 = internal global i64 0 518 | @trcauthstatus = internal global i64 0 519 | @trccidr2 = internal global i64 0 520 | @trcdevarch = internal global i64 0 521 | @trccidr3 = internal global i64 0 522 | @teecr32_el1 = internal global i64 0 523 | @teehbr32_el1 = internal global i64 0 524 | @mdccsr_el0 = internal global i64 0 525 | @dbgdtr_el0 = internal global i64 0 526 | @dbgdtrrx_el0 = internal global i64 0 527 | @dbgvcr32_el2 = internal global i64 0 528 | @midr_el1 = internal global i64 0 529 | @mpidr_el1 = internal global i64 0 530 | @revidr_el1 = internal global i64 0 531 | @id_pfr0_el1 = internal global i64 0 532 | @id_pfr1_el1 = internal global i64 0 533 | @id_dfr0_el1 = internal global i64 0 534 | @id_afr0_el1 = internal global i64 0 535 | @id_mmfr0_el1 = internal global i64 0 536 | @id_mmfr1_el1 = internal global i64 0 537 | @id_mmfr2_el1 = internal global i64 0 538 | @id_mmfr3_el1 = internal global i64 0 539 | @id_isar0_el1 = internal global i64 0 540 | @id_isar1_el1 = internal global i64 0 541 | @id_isar2_el1 = internal global i64 0 542 | @id_isar3_el1 = internal global i64 0 543 | @id_isar4_el1 = internal global i64 0 544 | @id_isar5_el1 = internal global i64 0 545 | @mvfr0_el1 = internal global i64 0 546 | @mvfr1_el1 = internal global i64 0 547 | @mvfr2_el1 = internal global i64 0 548 | @id_aa64pfr0_el1 = internal global i64 0 549 | @id_aa64pfr1_el1 = internal global i64 0 550 | @id_aa64dfr0_el1 = internal global i64 0 551 | @id_aa64dfr1_el1 = internal global i64 0 552 | @id_aa64afr0_el1 = internal global i64 0 553 | @id_aa64afr1_el1 = internal global i64 0 554 | @id_aa64isar0_el1 = internal global i64 0 555 | @id_aa64isar1_el1 = internal global i64 0 556 | @id_aa64mmfr0_el1 = internal global i64 0 557 | @id_aa64mmfr1_el1 = internal global i64 0 558 | @sctlr_el1 = internal global i64 0 559 | @actlr_el1 = internal global i64 0 560 | @cpacr_el1 = internal global i64 0 561 | @ttbr0_el1 = internal global i64 0 562 | @ttbr1_el1 = internal global i64 0 563 | @tcr_el1 = internal global i64 0 564 | @spsr_el1 = internal global i64 0 565 | @elr_el1 = internal global i64 0 566 | @sp_el0 = internal global i64 0 567 | @spsel.3 = internal global i64 0 568 | @currentel = internal global i64 0 569 | @icc_pmr_el1 = internal global i64 0 570 | @afsr0_el1 = internal global i64 0 571 | @afsr1_el1 = internal global i64 0 572 | @esr_el1 = internal global i64 0 573 | @far_el1 = internal global i64 0 574 | @par_el1 = internal global i64 0 575 | @pmintenset_el1 = internal global i64 0 576 | @pmintenclr_el1 = internal global i64 0 577 | @mair_el1 = internal global i64 0 578 | @amair_el1 = internal global i64 0 579 | @vbar_el1 = internal global i64 0 580 | @rvbar_el1 = internal global i64 0 581 | @rmr_el1 = internal global i64 0 582 | @isr_el1 = internal global i64 0 583 | @icc_iar0_el1 = internal global i64 0 584 | @icc_hppir0_el1 = internal global i64 0 585 | @icc_bpr0_el1 = internal global i64 0 586 | @icc_ap0r0_el1 = internal global i64 0 587 | @icc_ap0r1_el1 = internal global i64 0 588 | @icc_ap0r2_el1 = internal global i64 0 589 | @icc_ap0r3_el1 = internal global i64 0 590 | @icc_ap1r0_el1 = internal global i64 0 591 | @icc_ap1r1_el1 = internal global i64 0 592 | @icc_ap1r2_el1 = internal global i64 0 593 | @icc_ap1r3_el1 = internal global i64 0 594 | @icc_rpr_el1 = internal global i64 0 595 | @icc_iar1_el1 = internal global i64 0 596 | @icc_hppir1_el1 = internal global i64 0 597 | @icc_bpr1_el1 = internal global i64 0 598 | @icc_ctlr_el1 = internal global i64 0 599 | @icc_sre_el1 = internal global i64 0 600 | @icc_igrpen0_el1 = internal global i64 0 601 | @icc_igrpen1_el1 = internal global i64 0 602 | @icc_seien_el1 = internal global i64 0 603 | @contextidr_el1 = internal global i64 0 604 | @tpidr_el1 = internal global i64 0 605 | @cntkctl_el1 = internal global i64 0 606 | @ccsidr_el1 = internal global i64 0 607 | @clidr_el1 = internal global i64 0 608 | @aidr_el1 = internal global i64 0 609 | @csselr_el1 = internal global i64 0 610 | @ctr_el0 = internal global i64 0 611 | @dczid_el0 = internal global i64 0 612 | @nzcv = internal global i64 0 613 | @daif = internal global i64 0 614 | @fpcr = internal global i64 0 615 | @fpsr = internal global i64 0 616 | @dspsr_el0 = internal global i64 0 617 | @dlr_el0 = internal global i64 0 618 | @pmcr_el0 = internal global i64 0 619 | @pmcntenset_el0 = internal global i64 0 620 | @pmcntenclr_el0 = internal global i64 0 621 | @pmovsclr_el0 = internal global i64 0 622 | @pmselr_el0 = internal global i64 0 623 | @pmceid0_el0 = internal global i64 0 624 | @pmceid1_el0 = internal global i64 0 625 | @pmccntr_el0 = internal global i64 0 626 | @pmxevtyper_el0 = internal global i64 0 627 | @pmxevcntr_el0 = internal global i64 0 628 | @pmuserenr_el0 = internal global i64 0 629 | @pmovsset_el0 = internal global i64 0 630 | @tpidr_el0 = internal global i64 0 631 | @tpidrro_el0 = internal global i64 0 632 | @cntfrq_el0 = internal global i64 0 633 | @cntpct_el0 = internal global i64 0 634 | @cntvct_el0 = internal global i64 0 635 | @cntp_tval_el0 = internal global i64 0 636 | @cntp_ctl_el0 = internal global i64 0 637 | @cntp_cval_el0 = internal global i64 0 638 | @cntv_tval_el0 = internal global i64 0 639 | @cntv_ctl_el0 = internal global i64 0 640 | @cntv_cval_el0 = internal global i64 0 641 | @pmevcntr0_el0 = internal global i64 0 642 | @pmevcntr1_el0 = internal global i64 0 643 | @pmevcntr2_el0 = internal global i64 0 644 | @pmevcntr3_el0 = internal global i64 0 645 | @pmevcntr4_el0 = internal global i64 0 646 | @pmevcntr5_el0 = internal global i64 0 647 | @pmevcntr6_el0 = internal global i64 0 648 | @pmevcntr7_el0 = internal global i64 0 649 | @pmevcntr8_el0 = internal global i64 0 650 | @pmevcntr9_el0 = internal global i64 0 651 | @pmevcntr10_el0 = internal global i64 0 652 | @pmevcntr11_el0 = internal global i64 0 653 | @pmevcntr12_el0 = internal global i64 0 654 | @pmevcntr13_el0 = internal global i64 0 655 | @pmevcntr14_el0 = internal global i64 0 656 | @pmevcntr15_el0 = internal global i64 0 657 | @pmevcntr16_el0 = internal global i64 0 658 | @pmevcntr17_el0 = internal global i64 0 659 | @pmevcntr18_el0 = internal global i64 0 660 | @pmevcntr19_el0 = internal global i64 0 661 | @pmevcntr20_el0 = internal global i64 0 662 | @pmevcntr21_el0 = internal global i64 0 663 | @pmevcntr22_el0 = internal global i64 0 664 | @pmevcntr23_el0 = internal global i64 0 665 | @pmevcntr24_el0 = internal global i64 0 666 | @pmevcntr25_el0 = internal global i64 0 667 | @pmevcntr26_el0 = internal global i64 0 668 | @pmevcntr27_el0 = internal global i64 0 669 | @pmevcntr28_el0 = internal global i64 0 670 | @pmevcntr29_el0 = internal global i64 0 671 | @pmevcntr30_el0 = internal global i64 0 672 | @pmevtyper0_el0 = internal global i64 0 673 | @pmevtyper1_el0 = internal global i64 0 674 | @pmevtyper2_el0 = internal global i64 0 675 | @pmevtyper3_el0 = internal global i64 0 676 | @pmevtyper4_el0 = internal global i64 0 677 | @pmevtyper5_el0 = internal global i64 0 678 | @pmevtyper6_el0 = internal global i64 0 679 | @pmevtyper7_el0 = internal global i64 0 680 | @pmevtyper8_el0 = internal global i64 0 681 | @pmevtyper9_el0 = internal global i64 0 682 | @pmevtyper10_el0 = internal global i64 0 683 | @pmevtyper11_el0 = internal global i64 0 684 | @pmevtyper12_el0 = internal global i64 0 685 | @pmevtyper13_el0 = internal global i64 0 686 | @pmevtyper14_el0 = internal global i64 0 687 | @pmevtyper15_el0 = internal global i64 0 688 | @pmevtyper16_el0 = internal global i64 0 689 | @pmevtyper17_el0 = internal global i64 0 690 | @pmevtyper18_el0 = internal global i64 0 691 | @pmevtyper19_el0 = internal global i64 0 692 | @pmevtyper20_el0 = internal global i64 0 693 | @pmevtyper21_el0 = internal global i64 0 694 | @pmevtyper22_el0 = internal global i64 0 695 | @pmevtyper23_el0 = internal global i64 0 696 | @pmevtyper24_el0 = internal global i64 0 697 | @pmevtyper25_el0 = internal global i64 0 698 | @pmevtyper26_el0 = internal global i64 0 699 | @pmevtyper27_el0 = internal global i64 0 700 | @pmevtyper28_el0 = internal global i64 0 701 | @pmevtyper29_el0 = internal global i64 0 702 | @pmevtyper30_el0 = internal global i64 0 703 | @pmccfiltr_el0 = internal global i64 0 704 | @vpidr_el2 = internal global i64 0 705 | @vmpidr_el2 = internal global i64 0 706 | @sctlr_el2 = internal global i64 0 707 | @actlr_el2 = internal global i64 0 708 | @hcr_el2 = internal global i64 0 709 | @mdcr_el2 = internal global i64 0 710 | @cptr_el2 = internal global i64 0 711 | @hstr_el2 = internal global i64 0 712 | @hacr_el2 = internal global i64 0 713 | @ttbr0_el2 = internal global i64 0 714 | @tcr_el2 = internal global i64 0 715 | @vttbr_el2 = internal global i64 0 716 | @vtcr_el2 = internal global i64 0 717 | @dacr32_el2 = internal global i64 0 718 | @spsr_el2 = internal global i64 0 719 | @elr_el2 = internal global i64 0 720 | @sp_el1 = internal global i64 0 721 | @spsr_irq = internal global i64 0 722 | @spsr_abt = internal global i64 0 723 | @spsr_und = internal global i64 0 724 | @spsr_fiq = internal global i64 0 725 | @ifsr32_el2 = internal global i64 0 726 | @afsr0_el2 = internal global i64 0 727 | @afsr1_el2 = internal global i64 0 728 | @esr_el2 = internal global i64 0 729 | @fpexc32_el2 = internal global i64 0 730 | @far_el2 = internal global i64 0 731 | @hpfar_el2 = internal global i64 0 732 | @mair_el2 = internal global i64 0 733 | @amair_el2 = internal global i64 0 734 | @vbar_el2 = internal global i64 0 735 | @rvbar_el2 = internal global i64 0 736 | @rmr_el2 = internal global i64 0 737 | @ich_ap0r0_el2 = internal global i64 0 738 | @ich_ap0r1_el2 = internal global i64 0 739 | @ich_ap0r2_el2 = internal global i64 0 740 | @ich_ap0r3_el2 = internal global i64 0 741 | @ich_ap1r0_el2 = internal global i64 0 742 | @ich_ap1r1_el2 = internal global i64 0 743 | @ich_ap1r2_el2 = internal global i64 0 744 | @ich_ap1r3_el2 = internal global i64 0 745 | @ich_vseir_el2 = internal global i64 0 746 | @icc_sre_el2 = internal global i64 0 747 | @ich_hcr_el2 = internal global i64 0 748 | @ich_vtr_el2 = internal global i64 0 749 | @ich_misr_el2 = internal global i64 0 750 | @ich_eisr_el2 = internal global i64 0 751 | @ich_elsr_el2 = internal global i64 0 752 | @ich_vmcr_el2 = internal global i64 0 753 | @ich_lr0_el2 = internal global i64 0 754 | @ich_lr1_el2 = internal global i64 0 755 | @ich_lr2_el2 = internal global i64 0 756 | @ich_lr3_el2 = internal global i64 0 757 | @ich_lr4_el2 = internal global i64 0 758 | @ich_lr5_el2 = internal global i64 0 759 | @ich_lr6_el2 = internal global i64 0 760 | @ich_lr7_el2 = internal global i64 0 761 | @ich_lr8_el2 = internal global i64 0 762 | @ich_lr9_el2 = internal global i64 0 763 | @ich_lr10_el2 = internal global i64 0 764 | @ich_lr11_el2 = internal global i64 0 765 | @ich_lr12_el2 = internal global i64 0 766 | @ich_lr13_el2 = internal global i64 0 767 | @ich_lr14_el2 = internal global i64 0 768 | @ich_lr15_el2 = internal global i64 0 769 | @tpidr_el2 = internal global i64 0 770 | @cntvoff_el2 = internal global i64 0 771 | @cnthctl_el2 = internal global i64 0 772 | @cnthp_tval_el2 = internal global i64 0 773 | @cnthp_ctl_el2 = internal global i64 0 774 | @cnthp_cval_el2 = internal global i64 0 775 | @sctlr_el3 = internal global i64 0 776 | @actlr_el3 = internal global i64 0 777 | @scr_el3 = internal global i64 0 778 | @sder32_el3 = internal global i64 0 779 | @cptr_el3 = internal global i64 0 780 | @mdcr_el3 = internal global i64 0 781 | @ttbr0_el3 = internal global i64 0 782 | @tcr_el3 = internal global i64 0 783 | @spsr_el3 = internal global i64 0 784 | @elr_el3 = internal global i64 0 785 | @sp_el2 = internal global i64 0 786 | @afsr0_el3 = internal global i64 0 787 | @afsr1_el3 = internal global i64 0 788 | @esr_el3 = internal global i64 0 789 | @far_el3 = internal global i64 0 790 | @mair_el3 = internal global i64 0 791 | @amair_el3 = internal global i64 0 792 | @vbar_el3 = internal global i64 0 793 | @rvbar_el3 = internal global i64 0 794 | @rmr_el3 = internal global i64 0 795 | @icc_ctlr_el3 = internal global i64 0 796 | @icc_sre_el3 = internal global i64 0 797 | @icc_igrpen1_el3 = internal global i64 0 798 | @tpidr_el3 = internal global i64 0 799 | @cntps_tval_el1 = internal global i64 0 800 | @cntps_ctl_el1 = internal global i64 0 801 | @cntps_cval_el1 = internal global i64 0 802 | 803 | define void @root() { 804 | entry: 805 | store volatile i64 0, i64* @capstone_asm2llvm 806 | %0 = load i64, i64* @x30 807 | call void @capstone_return(i64 %0) 808 | ret void 809 | } 810 | 811 | declare void @capstone_call(i64) 812 | 813 | declare void @capstone_return(i64) 814 | 815 | declare void @capstone_branch(i64) 816 | 817 | declare void @capstone_branch_cond(i1, i64) 818 | -------------------------------------------------------------------------------- /in/ret.rem: -------------------------------------------------------------------------------- 1 | ; ModuleID = 'lifted_code' 2 | source_filename = "lifted_code" 3 | target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" 4 | target triple = "aarch64-pc-linux-gnu-elf" 5 | 6 | %struct.State = type { %struct.AArch64State } 7 | %struct.AArch64State = type { %struct.ArchState, %struct.SIMD, i64, %struct.GPR, i64, %union.anon, %union.anon, %union.anon, i64, %struct.SR, i64 } 8 | %struct.ArchState = type { i32, i32, %union.anon } 9 | %struct.SIMD = type { [32 x %union.vec128_t] } 10 | %union.vec128_t = type { %struct.uint128v1_t } 11 | %struct.uint128v1_t = type { [1 x i128] } 12 | %struct.GPR = type { i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg } 13 | %struct.Reg = type { %union.anon } 14 | %union.anon = type { i64 } 15 | %struct.SR = type { i64, %struct.Reg, i64, %struct.Reg, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, [6 x i8] } 16 | 17 | define ptr @sub_0(ptr noalias %state, i64 %program_counter, ptr noalias %memory) { 18 | %X30 = getelementptr inbounds %struct.State, ptr %state, i32 0, i32 0, i32 3, i32 61, i32 0, i32 0 19 | %BRANCH_TAKEN = alloca i8, align 4 20 | %RETURN_PC = alloca i64, align 8 21 | %MONITOR = alloca i64, align 8 22 | %STATE = alloca ptr, align 8 23 | store ptr %state, ptr %STATE, align 8 24 | %MEMORY = alloca ptr, align 8 25 | store ptr %memory, ptr %MEMORY, align 8 26 | %NEXT_PC = alloca i64, align 8 27 | store i64 %program_counter, ptr %NEXT_PC, align 8 28 | %WZR = alloca i32, align 4 29 | store i32 0, ptr %WZR, align 4 30 | %XZR = alloca i64, align 8 31 | store i64 0, ptr %XZR, align 8 32 | %IGNORE_WRITE_TO_WZR = alloca i32, align 4 33 | %IGNORE_WRITE_TO_XZR = alloca i64, align 8 34 | %SUPPRESS_WRITEBACK = alloca i64, align 8 35 | %PC = getelementptr inbounds %struct.State, ptr %state, i32 0, i32 0, i32 3, i32 65, i32 0, i32 0 36 | store i64 %program_counter, ptr %NEXT_PC, align 8 37 | br label %1 38 | 39 | 1: ; preds = %0 40 | %2 = load i64, ptr %NEXT_PC, align 8 41 | store i64 %2, ptr %PC, align 8 42 | %3 = add i64 %2, 4 43 | store i64 %3, ptr %NEXT_PC, align 8 44 | %4 = load i64, ptr %X30, align 8 45 | %5 = load ptr, ptr %MEMORY, align 8 46 | %qword.i = getelementptr inbounds %struct.State, ptr %state, i64 0, i32 0, i32 3, i32 65, i32 0, i32 0 47 | store i64 %4, ptr %qword.i, align 16 48 | store i64 %4, ptr %NEXT_PC, align 8 49 | store ptr %5, ptr %MEMORY, align 8 50 | %6 = load i64, ptr %NEXT_PC, align 8 51 | store i64 %6, ptr %PC, align 8 52 | %7 = load ptr, ptr %MEMORY, align 8 53 | %8 = load i64, ptr %PC, align 8 54 | %9 = tail call ptr @__remill_function_return(ptr %state, i64 %8, ptr %7) 55 | ret ptr %9 56 | } 57 | 58 | ; Function Attrs: noduplicate noinline nounwind optnone 59 | declare dso_local ptr @__remill_function_return(ptr noundef nonnull align 1, i64 noundef, ptr noundef) #0 60 | 61 | attributes #0 = { noduplicate noinline nounwind optnone "frame-pointer"="all" "no-builtins" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "tune-cpu"="generic" } 62 | -------------------------------------------------------------------------------- /in/ret2.rem: -------------------------------------------------------------------------------- 1 | ; ModuleID = 'll/ret.rem' 2 | source_filename = "lifted_code" 3 | target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" 4 | target triple = "aarch64-pc-linux-gnu-elf" 5 | 6 | %struct.State = type { %struct.AArch64State } 7 | %struct.AArch64State = type { %struct.ArchState, %struct.SIMD, i64, %struct.GPR, i64, %union.anon, %union.anon, %union.anon, i64, %struct.SR, i64 } 8 | %struct.ArchState = type { i32, i32, %union.anon } 9 | %struct.SIMD = type { [32 x %union.vec128_t] } 10 | %union.vec128_t = type { %struct.uint128v1_t } 11 | %struct.uint128v1_t = type { [1 x i128] } 12 | %struct.GPR = type { i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg } 13 | %struct.Reg = type { %union.anon } 14 | %union.anon = type { i64 } 15 | %struct.SR = type { i64, %struct.Reg, i64, %struct.Reg, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, [6 x i8] } 16 | 17 | define void @sub_0(ptr nonnull noundef %state, i64 %program_counter, ptr nonnull noundef %memory) { 18 | %X30 = getelementptr inbounds %struct.State, ptr %state, i32 0, i32 0, i32 3, i32 61, i32 0, i32 0 19 | %PC = getelementptr inbounds %struct.State, ptr %state, i32 0, i32 0, i32 3, i32 65, i32 0, i32 0 20 | %1 = load i64, ptr %X30, align 8 21 | store i64 %1, ptr %PC, align 8 22 | ret void 23 | } 24 | 25 | ; Function Attrs: noduplicate noinline nounwind optnone 26 | declare dso_local ptr @__remill_function_return(ptr noundef nonnull align 1, i64 noundef, ptr noundef) #0 27 | 28 | attributes #0 = { noduplicate noinline nounwind optnone "frame-pointer"="all" "no-builtins" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "tune-cpu"="generic" } 29 | -------------------------------------------------------------------------------- /out/adds.asl: -------------------------------------------------------------------------------- 1 | ; ModuleID = './lib/state.ll' 2 | source_filename = "/nonexistent.ll" 3 | 4 | @X0 = global i64 0 5 | @X1 = global i64 0 6 | @X2 = global i64 0 7 | @X3 = global i64 0 8 | @X4 = global i64 0 9 | @X5 = global i64 0 10 | @X6 = global i64 0 11 | @X7 = global i64 0 12 | @X8 = global i64 0 13 | @X9 = global i64 0 14 | @X10 = global i64 0 15 | @X11 = global i64 0 16 | @X12 = global i64 0 17 | @X13 = global i64 0 18 | @X14 = global i64 0 19 | @X15 = global i64 0 20 | @X16 = global i64 0 21 | @X17 = global i64 0 22 | @X18 = global i64 0 23 | @X19 = global i64 0 24 | @X20 = global i64 0 25 | @X21 = global i64 0 26 | @X22 = global i64 0 27 | @X23 = global i64 0 28 | @X24 = global i64 0 29 | @X25 = global i64 0 30 | @X26 = global i64 0 31 | @X27 = global i64 0 32 | @X28 = global i64 0 33 | @X29 = global i64 0 34 | @X30 = global i64 0 35 | @X31 = global i64 0 36 | @V0 = global i128 0 37 | @V1 = global i128 0 38 | @V2 = global i128 0 39 | @V3 = global i128 0 40 | @V4 = global i128 0 41 | @V5 = global i128 0 42 | @V6 = global i128 0 43 | @V7 = global i128 0 44 | @V8 = global i128 0 45 | @V9 = global i128 0 46 | @V10 = global i128 0 47 | @V11 = global i128 0 48 | @V12 = global i128 0 49 | @V13 = global i128 0 50 | @V14 = global i128 0 51 | @V15 = global i128 0 52 | @V16 = global i128 0 53 | @V17 = global i128 0 54 | @V18 = global i128 0 55 | @V19 = global i128 0 56 | @V20 = global i128 0 57 | @V21 = global i128 0 58 | @V22 = global i128 0 59 | @V23 = global i128 0 60 | @V24 = global i128 0 61 | @V25 = global i128 0 62 | @V26 = global i128 0 63 | @V27 = global i128 0 64 | @V28 = global i128 0 65 | @V29 = global i128 0 66 | @V30 = global i128 0 67 | @V31 = global i128 0 68 | @NF = global i1 false 69 | @ZF = global i1 false 70 | @CF = global i1 false 71 | @VF = global i1 false 72 | @PC = global i64 0 73 | 74 | define void @root() { 75 | entry: 76 | %__BranchTaken = alloca i1, align 1 77 | %nRW = alloca i1, align 1 78 | %BTypeNext = alloca i2, align 1 79 | store i1 false, ptr %__BranchTaken, align 1 80 | br label %0 81 | 82 | 0: ; preds = %entry 83 | %Exp7__5 = alloca i64, align 8 84 | %1 = load i64, ptr @X2, align 4 85 | store i64 %1, ptr %Exp7__5, align 4 86 | br label %2 87 | 88 | 2: ; preds = %0 89 | %Exp10__6 = alloca i64, align 8 90 | %3 = load i64, ptr @X3, align 4 91 | store i64 %3, ptr %Exp10__6, align 4 92 | br label %4 93 | 94 | 4: ; preds = %2 95 | %If22__5 = alloca i1, align 1 96 | br label %5 97 | 98 | 5: ; preds = %4 99 | %6 = load i64, ptr %Exp7__5, align 4 100 | %7 = load i64, ptr %Exp10__6, align 4 101 | %8 = add i64 %6, %7 102 | %9 = icmp eq i64 %8, 0 103 | br i1 %9, label %10, label %12 104 | 105 | 10: ; preds = %5 106 | store i1 true, ptr %If22__5, align 1 107 | br label %11 108 | 109 | 11: ; preds = %10 110 | br label %14 111 | 112 | 12: ; preds = %5 113 | store i1 false, ptr %If22__5, align 1 114 | br label %13 115 | 116 | 13: ; preds = %12 117 | br label %14 118 | 119 | 14: ; preds = %13, %11 120 | br label %15 121 | 122 | 15: ; preds = %14 123 | %If24__5 = alloca i1, align 1 124 | br label %16 125 | 126 | 16: ; preds = %15 127 | %17 = load i64, ptr %Exp7__5, align 4 128 | %18 = load i64, ptr %Exp10__6, align 4 129 | %19 = add i64 %17, %18 130 | %20 = zext i64 %19 to i66 131 | %21 = load i64, ptr %Exp7__5, align 4 132 | %22 = zext i64 %21 to i66 133 | %23 = load i64, ptr %Exp10__6, align 4 134 | %24 = zext i64 %23 to i66 135 | %25 = add i66 %22, %24 136 | %26 = icmp eq i66 %20, %25 137 | br i1 %26, label %27, label %29 138 | 139 | 27: ; preds = %16 140 | store i1 false, ptr %If24__5, align 1 141 | br label %28 142 | 143 | 28: ; preds = %27 144 | br label %31 145 | 146 | 29: ; preds = %16 147 | store i1 true, ptr %If24__5, align 1 148 | br label %30 149 | 150 | 30: ; preds = %29 151 | br label %31 152 | 153 | 31: ; preds = %30, %28 154 | br label %32 155 | 156 | 32: ; preds = %31 157 | %If26__5 = alloca i1, align 1 158 | br label %33 159 | 160 | 33: ; preds = %32 161 | %34 = load i64, ptr %Exp7__5, align 4 162 | %35 = load i64, ptr %Exp10__6, align 4 163 | %36 = add i64 %34, %35 164 | %37 = sext i64 %36 to i65 165 | %38 = load i64, ptr %Exp7__5, align 4 166 | %39 = sext i64 %38 to i65 167 | %40 = load i64, ptr %Exp10__6, align 4 168 | %41 = sext i64 %40 to i65 169 | %42 = add i65 %39, %41 170 | %43 = icmp eq i65 %37, %42 171 | br i1 %43, label %44, label %46 172 | 173 | 44: ; preds = %33 174 | store i1 false, ptr %If26__5, align 1 175 | br label %45 176 | 177 | 45: ; preds = %44 178 | br label %48 179 | 180 | 46: ; preds = %33 181 | store i1 true, ptr %If26__5, align 1 182 | br label %47 183 | 184 | 47: ; preds = %46 185 | br label %48 186 | 187 | 48: ; preds = %47, %45 188 | br label %49 189 | 190 | 49: ; preds = %48 191 | %50 = load i1, ptr %If26__5, align 1 192 | store i1 %50, ptr @VF, align 1 193 | br label %51 194 | 195 | 51: ; preds = %49 196 | %52 = load i1, ptr %If24__5, align 1 197 | store i1 %52, ptr @CF, align 1 198 | br label %53 199 | 200 | 53: ; preds = %51 201 | %54 = load i1, ptr %If22__5, align 1 202 | store i1 %54, ptr @ZF, align 1 203 | br label %55 204 | 205 | 55: ; preds = %53 206 | %56 = load i64, ptr %Exp7__5, align 4 207 | %57 = load i64, ptr %Exp10__6, align 4 208 | %58 = add i64 %56, %57 209 | %59 = lshr i64 %58, 63 210 | %60 = trunc i64 %59 to i1 211 | store i1 %60, ptr @NF, align 1 212 | br label %61 213 | 214 | 61: ; preds = %55 215 | %62 = load i64, ptr %Exp7__5, align 4 216 | %63 = load i64, ptr %Exp10__6, align 4 217 | %64 = add i64 %62, %63 218 | store i64 %64, ptr @X1, align 4 219 | br label %65 220 | 221 | 65: ; preds = %61 222 | %66 = load i1, ptr %__BranchTaken, align 1 223 | %67 = load i64, ptr @PC, align 4 224 | %68 = add i64 %67, 4 225 | %69 = select i1 %66, i64 %67, i64 %68 226 | store i64 %69, ptr @PC, align 4 227 | ret void 228 | } 229 | -------------------------------------------------------------------------------- /out/adds.cap: -------------------------------------------------------------------------------- 1 | ; ModuleID = '' 2 | source_filename = "test" 3 | target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128" 4 | 5 | @X0 = global i64 0 6 | @X1 = global i64 0 7 | @X2 = global i64 0 8 | @X3 = global i64 0 9 | @X4 = global i64 0 10 | @X5 = global i64 0 11 | @X6 = global i64 0 12 | @X7 = global i64 0 13 | @X8 = global i64 0 14 | @X9 = global i64 0 15 | @X10 = global i64 0 16 | @X11 = global i64 0 17 | @X12 = global i64 0 18 | @X13 = global i64 0 19 | @X14 = global i64 0 20 | @X15 = global i64 0 21 | @X16 = global i64 0 22 | @X17 = global i64 0 23 | @X18 = global i64 0 24 | @X19 = global i64 0 25 | @X20 = global i64 0 26 | @X21 = global i64 0 27 | @X22 = global i64 0 28 | @X23 = global i64 0 29 | @X24 = global i64 0 30 | @X25 = global i64 0 31 | @X26 = global i64 0 32 | @X27 = global i64 0 33 | @X28 = global i64 0 34 | @X29 = global i64 0 35 | @X30 = global i64 0 36 | @X31 = global i64 0 37 | @V0 = global i128 0 38 | @V1 = global i128 0 39 | @V2 = global i128 0 40 | @V3 = global i128 0 41 | @V4 = global i128 0 42 | @V5 = global i128 0 43 | @V6 = global i128 0 44 | @V7 = global i128 0 45 | @V8 = global i128 0 46 | @V9 = global i128 0 47 | @V10 = global i128 0 48 | @V11 = global i128 0 49 | @V12 = global i128 0 50 | @V13 = global i128 0 51 | @V14 = global i128 0 52 | @V15 = global i128 0 53 | @V16 = global i128 0 54 | @V17 = global i128 0 55 | @V18 = global i128 0 56 | @V19 = global i128 0 57 | @V20 = global i128 0 58 | @V21 = global i128 0 59 | @V22 = global i128 0 60 | @V23 = global i128 0 61 | @V24 = global i128 0 62 | @V25 = global i128 0 63 | @V26 = global i128 0 64 | @V27 = global i128 0 65 | @V28 = global i128 0 66 | @V29 = global i128 0 67 | @V30 = global i128 0 68 | @V31 = global i128 0 69 | @NF = global i1 false 70 | @ZF = global i1 false 71 | @CF = global i1 false 72 | @VF = global i1 false 73 | @PC = global i64 0 74 | 75 | define void @root() { 76 | entry: 77 | %0 = load i64, ptr @X2, align 8 78 | %1 = load i64, ptr @X3, align 8 79 | %2 = add i64 %0, %1 80 | store i64 %2, ptr @X1, align 8 81 | %3 = icmp ult i64 %2, %0 82 | store i1 %3, ptr @CF, align 1 83 | %4 = xor i64 %0, %2 84 | %5 = xor i64 %1, %2 85 | %6 = and i64 %4, %5 86 | %7 = icmp slt i64 %6, 0 87 | store i1 %7, ptr @VF, align 1 88 | %8 = icmp slt i64 %2, 0 89 | store i1 %8, ptr @NF, align 1 90 | %9 = icmp eq i64 %2, 0 91 | store i1 %9, ptr @ZF, align 1 92 | %10 = load i64, ptr @PC, align 8 93 | %11 = add i64 %10, 4 94 | store i64 %11, ptr @PC, align 8 95 | ret void 96 | } 97 | 98 | declare void @capstone_call(i64) 99 | 100 | define void @capstone_return(i64 %0) { 101 | %2 = sub i64 %0, 4 102 | store i64 %2, ptr @PC, align 8 103 | ret void 104 | } 105 | 106 | define void @capstone_branch(i64 %0) { 107 | %2 = sub i64 %0, 4 108 | store i64 %2, ptr @PC, align 8 109 | ret void 110 | } 111 | 112 | define void @capstone_branch_cond(i1 %0, i64 %1) { 113 | %3 = load i64, ptr @PC, align 8 114 | %4 = sub i64 %1, 4 115 | %5 = select i1 %0, i64 %4, i64 %3 116 | store i64 %5, ptr @PC, align 8 117 | ret void 118 | } 119 | -------------------------------------------------------------------------------- /out/adds.rem: -------------------------------------------------------------------------------- 1 | ; ModuleID = '../in/adds.rem' 2 | source_filename = "lifted_code" 3 | target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" 4 | 5 | @X0 = global i64 0 6 | @X1 = global i64 0 7 | @X2 = global i64 0 8 | @X3 = global i64 0 9 | @X4 = global i64 0 10 | @X5 = global i64 0 11 | @X6 = global i64 0 12 | @X7 = global i64 0 13 | @X8 = global i64 0 14 | @X9 = global i64 0 15 | @X10 = global i64 0 16 | @X11 = global i64 0 17 | @X12 = global i64 0 18 | @X13 = global i64 0 19 | @X14 = global i64 0 20 | @X15 = global i64 0 21 | @X16 = global i64 0 22 | @X17 = global i64 0 23 | @X18 = global i64 0 24 | @X19 = global i64 0 25 | @X20 = global i64 0 26 | @X21 = global i64 0 27 | @X22 = global i64 0 28 | @X23 = global i64 0 29 | @X24 = global i64 0 30 | @X25 = global i64 0 31 | @X26 = global i64 0 32 | @X27 = global i64 0 33 | @X28 = global i64 0 34 | @X29 = global i64 0 35 | @X30 = global i64 0 36 | @X31 = global i64 0 37 | @V0 = global i128 0 38 | @V1 = global i128 0 39 | @V2 = global i128 0 40 | @V3 = global i128 0 41 | @V4 = global i128 0 42 | @V5 = global i128 0 43 | @V6 = global i128 0 44 | @V7 = global i128 0 45 | @V8 = global i128 0 46 | @V9 = global i128 0 47 | @V10 = global i128 0 48 | @V11 = global i128 0 49 | @V12 = global i128 0 50 | @V13 = global i128 0 51 | @V14 = global i128 0 52 | @V15 = global i128 0 53 | @V16 = global i128 0 54 | @V17 = global i128 0 55 | @V18 = global i128 0 56 | @V19 = global i128 0 57 | @V20 = global i128 0 58 | @V21 = global i128 0 59 | @V22 = global i128 0 60 | @V23 = global i128 0 61 | @V24 = global i128 0 62 | @V25 = global i128 0 63 | @V26 = global i128 0 64 | @V27 = global i128 0 65 | @V28 = global i128 0 66 | @V29 = global i128 0 67 | @V30 = global i128 0 68 | @V31 = global i128 0 69 | @NF = global i1 false 70 | @ZF = global i1 false 71 | @CF = global i1 false 72 | @VF = global i1 false 73 | @PC = global i64 0 74 | 75 | ; Function Attrs: alwaysinline 76 | declare ptr @sub_0(ptr noalias, i64, ptr noalias) #0 77 | 78 | ; Function Attrs: alwaysinline mustprogress noduplicate nofree nosync nounwind readnone willreturn 79 | declare dso_local zeroext i1 @__remill_flag_computation_sign(i1 noundef zeroext, ...) #1 80 | 81 | ; Function Attrs: alwaysinline mustprogress noduplicate nofree nosync nounwind readnone willreturn 82 | declare dso_local zeroext i1 @__remill_flag_computation_zero(i1 noundef zeroext, ...) #1 83 | 84 | ; Function Attrs: alwaysinline mustprogress noduplicate nofree nosync nounwind readnone willreturn 85 | declare dso_local zeroext i1 @__remill_flag_computation_overflow(i1 noundef zeroext, ...) #1 86 | 87 | ; Function Attrs: alwaysinline noduplicate nounwind 88 | declare dso_local ptr @__remill_missing_block(ptr noundef nonnull align 1, i64 noundef, ptr noundef) #2 89 | 90 | define void @root() { 91 | %program_counter1 = load i64, ptr @PC, align 8 92 | %BRANCH_TAKEN = alloca i8, align 4 93 | %RETURN_PC = alloca i64, align 8 94 | %MONITOR = alloca i64, align 8 95 | %MEMORY = alloca ptr, align 8 96 | store ptr undef, ptr %MEMORY, align 8 97 | %NEXT_PC = alloca i64, align 8 98 | store i64 %program_counter1, ptr %NEXT_PC, align 8 99 | %WZR = alloca i32, align 4 100 | store i32 0, ptr %WZR, align 4 101 | %XZR = alloca i64, align 8 102 | store i64 0, ptr %XZR, align 8 103 | %IGNORE_WRITE_TO_WZR = alloca i32, align 4 104 | %IGNORE_WRITE_TO_XZR = alloca i64, align 8 105 | %SUPPRESS_WRITEBACK = alloca i64, align 8 106 | store i64 %program_counter1, ptr %NEXT_PC, align 8 107 | br label %1 108 | 109 | 1: ; preds = %0 110 | %2 = load i64, ptr %NEXT_PC, align 8 111 | store i64 %2, ptr @PC, align 8 112 | %3 = add i64 %2, 4 113 | store i64 %3, ptr %NEXT_PC, align 8 114 | %4 = load i64, ptr @X2, align 8 115 | %5 = load i64, ptr @X3, align 8 116 | %6 = load ptr, ptr %MEMORY, align 8 117 | %L.sroa.0.0.insert.ext.i.i.i = zext i64 %4 to i128 118 | %R.sroa.0.0.insert.ext.i.i.i = zext i64 %5 to i128 119 | %L.sroa.0.0.insert.insert.i77.i.i = add nuw nsw i128 %R.sroa.0.0.insert.ext.i.i.i, %L.sroa.0.0.insert.ext.i.i.i 120 | %retval.sroa.0.0.extract.trunc.i78.i.i = trunc i128 %L.sroa.0.0.insert.insert.i77.i.i to i64 121 | %7 = ashr i64 %4, 63 122 | %8 = ashr i64 %5, 63 123 | %L.sroa.2.0.insert.ext.i87.i.i = zext i64 %7 to i128 124 | %R.sroa.2.0.insert.ext.i.i.i = zext i64 %8 to i128 125 | %reass.add.i = add nuw nsw i128 %R.sroa.2.0.insert.ext.i.i.i, %L.sroa.2.0.insert.ext.i87.i.i 126 | %reass.mul.i = shl i128 %reass.add.i, 64 127 | %L.sroa.0.0.insert.insert.i107.i.i = add i128 %reass.mul.i, %L.sroa.0.0.insert.insert.i77.i.i 128 | %cmp.i.i.i = icmp slt i64 %retval.sroa.0.0.extract.trunc.i78.i.i, 0 129 | %conv.i.i = zext i1 %cmp.i.i.i to i8 130 | store i8 %conv.i.i, ptr @NF, align 1 131 | %cmp.i114.i.i = icmp eq i64 %retval.sroa.0.0.extract.trunc.i78.i.i, 0 132 | %conv34.i.i = zext i1 %cmp.i114.i.i to i8 133 | store i8 %conv34.i.i, ptr @ZF, align 1 134 | %L.sroa.0.0.insert.ext.i115.i.i = and i128 %L.sroa.0.0.insert.insert.i77.i.i, 18446744073709551615 135 | %9 = icmp ugt i128 %L.sroa.0.0.insert.insert.i77.i.i, 18446744073709551615 136 | %conv41.i.i = zext i1 %9 to i8 137 | store i8 %conv41.i.i, ptr @CF, align 1 138 | %10 = ashr i64 %retval.sroa.0.0.extract.trunc.i78.i.i, 63 139 | %L.sroa.2.0.insert.ext.i122.i.i = zext i64 %10 to i128 140 | %L.sroa.2.0.insert.shift.i123.i.i = shl nuw i128 %L.sroa.2.0.insert.ext.i122.i.i, 64 141 | %L.sroa.0.0.insert.insert.i125.i.i = or i128 %L.sroa.2.0.insert.shift.i123.i.i, %L.sroa.0.0.insert.ext.i115.i.i 142 | %cmp.i130.i.i = icmp ne i128 %L.sroa.0.0.insert.insert.i125.i.i, %L.sroa.0.0.insert.insert.i107.i.i 143 | %conv49.i.i = zext i1 %cmp.i130.i.i to i8 144 | store i8 %conv49.i.i, ptr @VF, align 1 145 | store i64 %retval.sroa.0.0.extract.trunc.i78.i.i, ptr @X1, align 8 146 | store ptr %6, ptr %MEMORY, align 8 147 | br label %11 148 | 149 | 11: ; preds = %1 150 | %12 = load i64, ptr %NEXT_PC, align 8 151 | store i64 %12, ptr @PC, align 8 152 | %13 = load ptr, ptr %MEMORY, align 8 153 | %14 = load i64, ptr @PC, align 8 154 | ret void 155 | } 156 | 157 | attributes #0 = { alwaysinline } 158 | attributes #1 = { alwaysinline mustprogress noduplicate nofree nosync nounwind readnone willreturn "frame-pointer"="none" "no-builtins" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "tune-cpu"="generic" } 159 | attributes #2 = { alwaysinline noduplicate nounwind "frame-pointer"="all" "no-builtins" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "tune-cpu"="generic" } 160 | -------------------------------------------------------------------------------- /out/adds.remo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UQ-PAC/llvm-translator/2110ff718c2f3bd8f428653b3f6ce471eb399adb/out/adds.remo -------------------------------------------------------------------------------- /out/addv.asl: -------------------------------------------------------------------------------- 1 | ; ModuleID = './lib/state.ll' 2 | source_filename = "/nonexistent.ll" 3 | 4 | @X0 = internal global i64 0 5 | @X1 = internal global i64 0 6 | @X2 = internal global i64 0 7 | @X3 = internal global i64 0 8 | @X4 = internal global i64 0 9 | @X5 = internal global i64 0 10 | @X6 = internal global i64 0 11 | @X7 = internal global i64 0 12 | @X8 = internal global i64 0 13 | @X9 = internal global i64 0 14 | @X10 = internal global i64 0 15 | @X11 = internal global i64 0 16 | @X12 = internal global i64 0 17 | @X13 = internal global i64 0 18 | @X14 = internal global i64 0 19 | @X15 = internal global i64 0 20 | @X16 = internal global i64 0 21 | @X17 = internal global i64 0 22 | @X18 = internal global i64 0 23 | @X19 = internal global i64 0 24 | @X20 = internal global i64 0 25 | @X21 = internal global i64 0 26 | @X22 = internal global i64 0 27 | @X23 = internal global i64 0 28 | @X24 = internal global i64 0 29 | @X25 = internal global i64 0 30 | @X26 = internal global i64 0 31 | @X27 = internal global i64 0 32 | @X28 = internal global i64 0 33 | @X29 = internal global i64 0 34 | @X30 = internal global i64 0 35 | @X31 = internal global i64 0 36 | @V0 = internal global i128 0 37 | @V1 = internal global i128 0 38 | @V2 = internal global i128 0 39 | @V3 = internal global i128 0 40 | @V4 = internal global i128 0 41 | @V5 = internal global i128 0 42 | @V6 = internal global i128 0 43 | @V7 = internal global i128 0 44 | @V8 = internal global i128 0 45 | @V9 = internal global i128 0 46 | @V10 = internal global i128 0 47 | @V11 = internal global i128 0 48 | @V12 = internal global i128 0 49 | @V13 = internal global i128 0 50 | @V14 = internal global i128 0 51 | @V15 = internal global i128 0 52 | @V16 = internal global i128 0 53 | @V17 = internal global i128 0 54 | @V18 = internal global i128 0 55 | @V19 = internal global i128 0 56 | @V20 = internal global i128 0 57 | @V21 = internal global i128 0 58 | @V22 = internal global i128 0 59 | @V23 = internal global i128 0 60 | @V24 = internal global i128 0 61 | @V25 = internal global i128 0 62 | @V26 = internal global i128 0 63 | @V27 = internal global i128 0 64 | @V28 = internal global i128 0 65 | @V29 = internal global i128 0 66 | @V30 = internal global i128 0 67 | @V31 = internal global i128 0 68 | @NF = internal global i1 false 69 | @ZF = internal global i1 false 70 | @CF = internal global i1 false 71 | @VF = internal global i1 false 72 | @PC = internal global i64 0 73 | 74 | define void @root() { 75 | entry: 76 | %__BranchTaken = alloca i1, align 1 77 | %nRW = alloca i1, align 1 78 | %BTypeNext = alloca i2, align 1 79 | store i1 false, i1* %__BranchTaken, align 1 80 | br label %stmt 81 | 82 | stmt: ; preds = %entry 83 | %Exp7__5 = alloca i128, align 8 84 | %0 = load i128, i128* @V1, align 4 85 | store i128 %0, i128* %Exp7__5, align 4 86 | br label %stmt1 87 | 88 | stmt1: ; preds = %stmt 89 | %Exp9__5 = alloca i128, align 8 90 | %1 = load i128, i128* @V2, align 4 91 | store i128 %1, i128* %Exp9__5, align 4 92 | br label %stmt2 93 | 94 | stmt2: ; preds = %stmt1 95 | %2 = load i128, i128* %Exp7__5, align 4 96 | %3 = lshr i128 %2, 96 97 | %4 = trunc i128 %3 to i32 98 | %5 = load i128, i128* %Exp9__5, align 4 99 | %6 = lshr i128 %5, 96 100 | %7 = trunc i128 %6 to i32 101 | %8 = add i32 %4, %7 102 | %9 = load i128, i128* %Exp7__5, align 4 103 | %10 = lshr i128 %9, 64 104 | %11 = trunc i128 %10 to i32 105 | %12 = load i128, i128* %Exp9__5, align 4 106 | %13 = lshr i128 %12, 64 107 | %14 = trunc i128 %13 to i32 108 | %15 = add i32 %11, %14 109 | %16 = load i128, i128* %Exp7__5, align 4 110 | %17 = lshr i128 %16, 32 111 | %18 = trunc i128 %17 to i32 112 | %19 = load i128, i128* %Exp9__5, align 4 113 | %20 = lshr i128 %19, 32 114 | %21 = trunc i128 %20 to i32 115 | %22 = add i32 %18, %21 116 | %23 = load i128, i128* %Exp7__5, align 4 117 | %24 = trunc i128 %23 to i32 118 | %25 = load i128, i128* %Exp9__5, align 4 119 | %26 = trunc i128 %25 to i32 120 | %27 = add i32 %24, %26 121 | %28 = zext i32 %22 to i64 122 | %29 = zext i32 %27 to i64 123 | %30 = shl i64 %28, 32 124 | %31 = or i64 %30, %29 125 | %32 = zext i32 %15 to i96 126 | %33 = zext i64 %31 to i96 127 | %34 = shl i96 %32, 64 128 | %35 = or i96 %34, %33 129 | %36 = zext i32 %8 to i128 130 | %37 = zext i96 %35 to i128 131 | %38 = shl i128 %36, 96 132 | %39 = or i128 %38, %37 133 | store i128 %39, i128* @V0, align 4 134 | br label %end 135 | 136 | end: ; preds = %stmt2 137 | %40 = load i1, i1* %__BranchTaken, align 1 138 | %41 = load i64, i64* @PC, align 4 139 | %42 = add i64 %41, 4 140 | %43 = select i1 %40, i64 %41, i64 %42 141 | store i64 %43, i64* @PC, align 4 142 | ret void 143 | } 144 | -------------------------------------------------------------------------------- /out/addv.rem: -------------------------------------------------------------------------------- 1 | ; ModuleID = '../in/addv.rem' 2 | source_filename = "lifted_code" 3 | target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" 4 | 5 | @X0 = global i64 0 6 | @X1 = global i64 0 7 | @X2 = global i64 0 8 | @X3 = global i64 0 9 | @X4 = global i64 0 10 | @X5 = global i64 0 11 | @X6 = global i64 0 12 | @X7 = global i64 0 13 | @X8 = global i64 0 14 | @X9 = global i64 0 15 | @X10 = global i64 0 16 | @X11 = global i64 0 17 | @X12 = global i64 0 18 | @X13 = global i64 0 19 | @X14 = global i64 0 20 | @X15 = global i64 0 21 | @X16 = global i64 0 22 | @X17 = global i64 0 23 | @X18 = global i64 0 24 | @X19 = global i64 0 25 | @X20 = global i64 0 26 | @X21 = global i64 0 27 | @X22 = global i64 0 28 | @X23 = global i64 0 29 | @X24 = global i64 0 30 | @X25 = global i64 0 31 | @X26 = global i64 0 32 | @X27 = global i64 0 33 | @X28 = global i64 0 34 | @X29 = global i64 0 35 | @X30 = global i64 0 36 | @X31 = global i64 0 37 | @V0 = global i128 0 38 | @V1 = global i128 0 39 | @V2 = global i128 0 40 | @V3 = global i128 0 41 | @V4 = global i128 0 42 | @V5 = global i128 0 43 | @V6 = global i128 0 44 | @V7 = global i128 0 45 | @V8 = global i128 0 46 | @V9 = global i128 0 47 | @V10 = global i128 0 48 | @V11 = global i128 0 49 | @V12 = global i128 0 50 | @V13 = global i128 0 51 | @V14 = global i128 0 52 | @V15 = global i128 0 53 | @V16 = global i128 0 54 | @V17 = global i128 0 55 | @V18 = global i128 0 56 | @V19 = global i128 0 57 | @V20 = global i128 0 58 | @V21 = global i128 0 59 | @V22 = global i128 0 60 | @V23 = global i128 0 61 | @V24 = global i128 0 62 | @V25 = global i128 0 63 | @V26 = global i128 0 64 | @V27 = global i128 0 65 | @V28 = global i128 0 66 | @V29 = global i128 0 67 | @V30 = global i128 0 68 | @V31 = global i128 0 69 | @NF = global i1 false 70 | @ZF = global i1 false 71 | @CF = global i1 false 72 | @VF = global i1 false 73 | @PC = global i64 0 74 | 75 | ; Function Attrs: alwaysinline 76 | declare ptr @sub_0(ptr noalias, i64, ptr noalias) #0 77 | 78 | ; Function Attrs: alwaysinline noduplicate nounwind 79 | declare dso_local ptr @__remill_missing_block(ptr noundef nonnull align 1, i64 noundef, ptr noundef) #1 80 | 81 | define void @root() { 82 | %program_counter1 = load i64, ptr @PC, align 8 83 | %BRANCH_TAKEN = alloca i8, align 4 84 | %RETURN_PC = alloca i64, align 8 85 | %MONITOR = alloca i64, align 8 86 | %MEMORY = alloca ptr, align 8 87 | store ptr undef, ptr %MEMORY, align 8 88 | %NEXT_PC = alloca i64, align 8 89 | store i64 %program_counter1, ptr %NEXT_PC, align 8 90 | %WZR = alloca i32, align 4 91 | store i32 0, ptr %WZR, align 4 92 | %XZR = alloca i64, align 8 93 | store i64 0, ptr %XZR, align 8 94 | %IGNORE_WRITE_TO_WZR = alloca i32, align 4 95 | %IGNORE_WRITE_TO_XZR = alloca i64, align 8 96 | %SUPPRESS_WRITEBACK = alloca i64, align 8 97 | store i64 %program_counter1, ptr %NEXT_PC, align 8 98 | br label %1 99 | 100 | 1: ; preds = %0 101 | %2 = load i64, ptr %NEXT_PC, align 8 102 | store i64 %2, ptr @PC, align 8 103 | %3 = add i64 %2, 4 104 | store i64 %3, ptr %NEXT_PC, align 8 105 | %4 = load ptr, ptr %MEMORY, align 8 106 | %retval.sroa.0.0.copyload.i.i = load i64, ptr @V1, align 1 107 | %retval.sroa.2.0..sroa_idx.i.i = getelementptr inbounds i8, ptr @V1, i64 8 108 | %retval.sroa.2.0.copyload.i.i = load i64, ptr %retval.sroa.2.0..sroa_idx.i.i, align 1 109 | %vec1.sroa.0.sroa.0.0.extract.trunc.i = trunc i64 %retval.sroa.0.0.copyload.i.i to i32 110 | %vec1.sroa.0.sroa.4.0.extract.shift.i = lshr i64 %retval.sroa.0.0.copyload.i.i, 32 111 | %vec1.sroa.0.sroa.4.0.extract.trunc.i = trunc i64 %vec1.sroa.0.sroa.4.0.extract.shift.i to i32 112 | %retval.sroa.0.0.copyload.i26.i = load i64, ptr @V2, align 1 113 | %retval.sroa.2.0..sroa_idx.i27.i = getelementptr inbounds i8, ptr @V2, i64 8 114 | %retval.sroa.2.0.copyload.i29.i = load i64, ptr %retval.sroa.2.0..sroa_idx.i27.i, align 1 115 | %vec2.sroa.0.sroa.0.0.extract.trunc.i = trunc i64 %retval.sroa.0.0.copyload.i26.i to i32 116 | %vec2.sroa.0.sroa.4.0.extract.shift.i = lshr i64 %retval.sroa.0.0.copyload.i26.i, 32 117 | %vec2.sroa.0.sroa.4.0.extract.trunc.i = trunc i64 %vec2.sroa.0.sroa.4.0.extract.shift.i to i32 118 | %add.i.i = add i32 %vec2.sroa.0.sroa.0.0.extract.trunc.i, %vec1.sroa.0.sroa.0.0.extract.trunc.i 119 | %add.i.1.i = add i32 %vec2.sroa.0.sroa.4.0.extract.trunc.i, %vec1.sroa.0.sroa.4.0.extract.trunc.i 120 | %vec1.sroa.5.8.extract.trunc.i = trunc i64 %retval.sroa.2.0.copyload.i.i to i32 121 | %vec2.sroa.5.8.extract.trunc.i = trunc i64 %retval.sroa.2.0.copyload.i29.i to i32 122 | %add.i.2.i = add i32 %vec2.sroa.5.8.extract.trunc.i, %vec1.sroa.5.8.extract.trunc.i 123 | %vec1.sroa.5.12.extract.shift.i = lshr i64 %retval.sroa.2.0.copyload.i.i, 32 124 | %vec1.sroa.5.12.extract.trunc.i = trunc i64 %vec1.sroa.5.12.extract.shift.i to i32 125 | %vec2.sroa.5.12.extract.shift.i = lshr i64 %retval.sroa.2.0.copyload.i29.i, 32 126 | %vec2.sroa.5.12.extract.trunc.i = trunc i64 %vec2.sroa.5.12.extract.shift.i to i32 127 | %add.i.3.i = add i32 %vec2.sroa.5.12.extract.trunc.i, %vec1.sroa.5.12.extract.trunc.i 128 | store i32 %add.i.i, ptr @V0, align 1 129 | %arrayidx2.1.i.i = getelementptr inbounds i8, ptr @V0, i64 4 130 | store i32 %add.i.1.i, ptr %arrayidx2.1.i.i, align 1 131 | %arrayidx2.2.i.i = getelementptr inbounds i8, ptr @V0, i64 8 132 | store i32 %add.i.2.i, ptr %arrayidx2.2.i.i, align 1 133 | %arrayidx2.3.i.i = getelementptr inbounds i8, ptr @V0, i64 12 134 | store i32 %add.i.3.i, ptr %arrayidx2.3.i.i, align 1 135 | store ptr %4, ptr %MEMORY, align 8 136 | br label %5 137 | 138 | 5: ; preds = %1 139 | %6 = load i64, ptr %NEXT_PC, align 8 140 | store i64 %6, ptr @PC, align 8 141 | %7 = load ptr, ptr %MEMORY, align 8 142 | %8 = load i64, ptr @PC, align 8 143 | ret void 144 | } 145 | 146 | attributes #0 = { alwaysinline } 147 | attributes #1 = { alwaysinline noduplicate nounwind "frame-pointer"="all" "no-builtins" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "tune-cpu"="generic" } 148 | -------------------------------------------------------------------------------- /out/addv2.asl: -------------------------------------------------------------------------------- 1 | ; ModuleID = '' 2 | source_filename = "/nonexistent.ll" 3 | 4 | @X0 = internal global i64 0 5 | @X1 = internal global i64 0 6 | @X2 = internal global i64 0 7 | @X3 = internal global i64 0 8 | @X4 = internal global i64 0 9 | @X5 = internal global i64 0 10 | @X6 = internal global i64 0 11 | @X7 = internal global i64 0 12 | @X8 = internal global i64 0 13 | @X9 = internal global i64 0 14 | @X10 = internal global i64 0 15 | @X11 = internal global i64 0 16 | @X12 = internal global i64 0 17 | @X13 = internal global i64 0 18 | @X14 = internal global i64 0 19 | @X15 = internal global i64 0 20 | @X16 = internal global i64 0 21 | @X17 = internal global i64 0 22 | @X18 = internal global i64 0 23 | @X19 = internal global i64 0 24 | @X20 = internal global i64 0 25 | @X21 = internal global i64 0 26 | @X22 = internal global i64 0 27 | @X23 = internal global i64 0 28 | @X24 = internal global i64 0 29 | @X25 = internal global i64 0 30 | @X26 = internal global i64 0 31 | @X27 = internal global i64 0 32 | @X28 = internal global i64 0 33 | @X29 = internal global i64 0 34 | @X30 = internal global i64 0 35 | @X31 = internal global i64 0 36 | @V0 = internal global i128 0 37 | @V1 = internal global i128 0 38 | @V2 = internal global i128 0 39 | @V3 = internal global i128 0 40 | @V4 = internal global i128 0 41 | @V5 = internal global i128 0 42 | @V6 = internal global i128 0 43 | @V7 = internal global i128 0 44 | @V8 = internal global i128 0 45 | @V9 = internal global i128 0 46 | @V10 = internal global i128 0 47 | @V11 = internal global i128 0 48 | @V12 = internal global i128 0 49 | @V13 = internal global i128 0 50 | @V14 = internal global i128 0 51 | @V15 = internal global i128 0 52 | @V16 = internal global i128 0 53 | @V17 = internal global i128 0 54 | @V18 = internal global i128 0 55 | @V19 = internal global i128 0 56 | @V20 = internal global i128 0 57 | @V21 = internal global i128 0 58 | @V22 = internal global i128 0 59 | @V23 = internal global i128 0 60 | @V24 = internal global i128 0 61 | @V25 = internal global i128 0 62 | @V26 = internal global i128 0 63 | @V27 = internal global i128 0 64 | @V28 = internal global i128 0 65 | @V29 = internal global i128 0 66 | @V30 = internal global i128 0 67 | @V31 = internal global i128 0 68 | @NF = internal global i1 false 69 | @ZF = internal global i1 false 70 | @CF = internal global i1 false 71 | @VF = internal global i1 false 72 | @PC = internal global i64 0 73 | 74 | define void @root() { 75 | entry: 76 | %0 = load i128, i128* @V1, align 4 77 | %1 = load i128, i128* @V2, align 4 78 | %2 = lshr i128 %0, 96 79 | %3 = trunc i128 %2 to i32 80 | %4 = lshr i128 %1, 96 81 | %5 = trunc i128 %4 to i32 82 | %6 = add i32 %3, %5 83 | %7 = lshr i128 %0, 64 84 | %8 = trunc i128 %7 to i32 85 | %9 = lshr i128 %1, 64 86 | %10 = trunc i128 %9 to i32 87 | %11 = add i32 %8, %10 88 | %12 = lshr i128 %0, 32 89 | %13 = trunc i128 %12 to i32 90 | %14 = lshr i128 %1, 32 91 | %15 = trunc i128 %14 to i32 92 | %16 = add i32 %13, %15 93 | %17 = trunc i128 %0 to i32 94 | %18 = trunc i128 %1 to i32 95 | %19 = add i32 %17, %18 96 | %20 = zext i32 %16 to i64 97 | %21 = zext i32 %19 to i64 98 | %22 = shl i64 %20, 32 99 | %23 = or i64 %22, %21 100 | %24 = zext i32 %11 to i96 101 | %25 = zext i64 %23 to i96 102 | %26 = shl i96 %24, 64 103 | %27 = or i96 %26, %25 104 | %28 = zext i32 %6 to i128 105 | %29 = zext i96 %27 to i128 106 | %30 = shl i128 %28, 96 107 | %31 = or i128 %30, %29 108 | store i128 %31, i128* @V0, align 4 109 | %32 = load i64, i64* @PC, align 4 110 | %33 = add i64 %32, 4 111 | store i64 %33, i64* @PC, align 4 112 | ret void 113 | } 114 | -------------------------------------------------------------------------------- /out/ldr.asl: -------------------------------------------------------------------------------- 1 | ; ModuleID = './lib/state.ll' 2 | source_filename = "/nonexistent.ll" 3 | 4 | @X0 = internal global i64 0 5 | @X1 = internal global i64 0 6 | @X2 = internal global i64 0 7 | @X3 = internal global i64 0 8 | @X4 = internal global i64 0 9 | @X5 = internal global i64 0 10 | @X6 = internal global i64 0 11 | @X7 = internal global i64 0 12 | @X8 = internal global i64 0 13 | @X9 = internal global i64 0 14 | @X10 = internal global i64 0 15 | @X11 = internal global i64 0 16 | @X12 = internal global i64 0 17 | @X13 = internal global i64 0 18 | @X14 = internal global i64 0 19 | @X15 = internal global i64 0 20 | @X16 = internal global i64 0 21 | @X17 = internal global i64 0 22 | @X18 = internal global i64 0 23 | @X19 = internal global i64 0 24 | @X20 = internal global i64 0 25 | @X21 = internal global i64 0 26 | @X22 = internal global i64 0 27 | @X23 = internal global i64 0 28 | @X24 = internal global i64 0 29 | @X25 = internal global i64 0 30 | @X26 = internal global i64 0 31 | @X27 = internal global i64 0 32 | @X28 = internal global i64 0 33 | @X29 = internal global i64 0 34 | @X30 = internal global i64 0 35 | @X31 = internal global i64 0 36 | @V0 = internal global i128 0 37 | @V1 = internal global i128 0 38 | @V2 = internal global i128 0 39 | @V3 = internal global i128 0 40 | @V4 = internal global i128 0 41 | @V5 = internal global i128 0 42 | @V6 = internal global i128 0 43 | @V7 = internal global i128 0 44 | @V8 = internal global i128 0 45 | @V9 = internal global i128 0 46 | @V10 = internal global i128 0 47 | @V11 = internal global i128 0 48 | @V12 = internal global i128 0 49 | @V13 = internal global i128 0 50 | @V14 = internal global i128 0 51 | @V15 = internal global i128 0 52 | @V16 = internal global i128 0 53 | @V17 = internal global i128 0 54 | @V18 = internal global i128 0 55 | @V19 = internal global i128 0 56 | @V20 = internal global i128 0 57 | @V21 = internal global i128 0 58 | @V22 = internal global i128 0 59 | @V23 = internal global i128 0 60 | @V24 = internal global i128 0 61 | @V25 = internal global i128 0 62 | @V26 = internal global i128 0 63 | @V27 = internal global i128 0 64 | @V28 = internal global i128 0 65 | @V29 = internal global i128 0 66 | @V30 = internal global i128 0 67 | @V31 = internal global i128 0 68 | @NF = internal global i1 false 69 | @ZF = internal global i1 false 70 | @CF = internal global i1 false 71 | @VF = internal global i1 false 72 | @PC = internal global i64 0 73 | 74 | define void @main() { 75 | entry: 76 | %__BranchTaken = alloca i1, align 1 77 | %nRW = alloca i1, align 1 78 | %BTypeNext = alloca i2, align 1 79 | store i1 false, ptr %__BranchTaken, align 1 80 | br label %stmt 81 | 82 | stmt: ; preds = %entry 83 | %Exp9__6 = alloca i64, align 8 84 | %0 = load i64, ptr @X3, align 4 85 | store i64 %0, ptr %Exp9__6, align 4 86 | br label %stmt1 87 | 88 | stmt1: ; preds = %stmt 89 | %Exp17__5 = alloca i64, align 8 90 | %1 = load i64, ptr @X2, align 4 91 | store i64 %1, ptr %Exp17__5, align 4 92 | br label %stmt2 93 | 94 | stmt2: ; preds = %stmt1 95 | %Exp18__5 = alloca i64, align 8 96 | %2 = load i64, ptr %Exp17__5, align 4 97 | %3 = load i64, ptr %Exp9__6, align 4 98 | %4 = add i64 %2, %3 99 | %5 = inttoptr i64 %4 to ptr 100 | %6 = load i64, ptr %5, align 4 101 | store i64 %6, ptr %Exp18__5, align 4 102 | br label %stmt3 103 | 104 | stmt3: ; preds = %stmt2 105 | %7 = load i64, ptr %Exp18__5, align 4 106 | store i64 %7, ptr @X1, align 4 107 | br label %8 108 | 109 | 8: ; preds = %stmt3 110 | %9 = load i1, ptr %__BranchTaken, align 1 111 | %10 = load i64, ptr @PC, align 4 112 | %11 = add i64 %10, 4 113 | %12 = select i1 %9, i64 %10, i64 %11 114 | store i64 %12, ptr @PC, align 4 115 | ret void 116 | } 117 | -------------------------------------------------------------------------------- /out/ldr.cap: -------------------------------------------------------------------------------- 1 | ; ModuleID = '' 2 | source_filename = "test" 3 | target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128" 4 | 5 | @X0 = global i64 0 6 | @X1 = global i64 0 7 | @X2 = global i64 0 8 | @X3 = global i64 0 9 | @X4 = global i64 0 10 | @X5 = global i64 0 11 | @X6 = global i64 0 12 | @X7 = global i64 0 13 | @X8 = global i64 0 14 | @X9 = global i64 0 15 | @X10 = global i64 0 16 | @X11 = global i64 0 17 | @X12 = global i64 0 18 | @X13 = global i64 0 19 | @X14 = global i64 0 20 | @X15 = global i64 0 21 | @X16 = global i64 0 22 | @X17 = global i64 0 23 | @X18 = global i64 0 24 | @X19 = global i64 0 25 | @X20 = global i64 0 26 | @X21 = global i64 0 27 | @X22 = global i64 0 28 | @X23 = global i64 0 29 | @X24 = global i64 0 30 | @X25 = global i64 0 31 | @X26 = global i64 0 32 | @X27 = global i64 0 33 | @X28 = global i64 0 34 | @X29 = global i64 0 35 | @X30 = global i64 0 36 | @X31 = global i64 0 37 | @V0 = global i128 0 38 | @V1 = global i128 0 39 | @V2 = global i128 0 40 | @V3 = global i128 0 41 | @V4 = global i128 0 42 | @V5 = global i128 0 43 | @V6 = global i128 0 44 | @V7 = global i128 0 45 | @V8 = global i128 0 46 | @V9 = global i128 0 47 | @V10 = global i128 0 48 | @V11 = global i128 0 49 | @V12 = global i128 0 50 | @V13 = global i128 0 51 | @V14 = global i128 0 52 | @V15 = global i128 0 53 | @V16 = global i128 0 54 | @V17 = global i128 0 55 | @V18 = global i128 0 56 | @V19 = global i128 0 57 | @V20 = global i128 0 58 | @V21 = global i128 0 59 | @V22 = global i128 0 60 | @V23 = global i128 0 61 | @V24 = global i128 0 62 | @V25 = global i128 0 63 | @V26 = global i128 0 64 | @V27 = global i128 0 65 | @V28 = global i128 0 66 | @V29 = global i128 0 67 | @V30 = global i128 0 68 | @V31 = global i128 0 69 | @NF = global i1 false 70 | @ZF = global i1 false 71 | @CF = global i1 false 72 | @VF = global i1 false 73 | @PC = global i64 0 74 | 75 | define void @root() { 76 | entry: 77 | %0 = load i64, ptr @X2, align 8 78 | %1 = load i64, ptr @X3, align 8 79 | %2 = add i64 %0, %1 80 | %3 = inttoptr i64 %2 to ptr 81 | %4 = load i64, ptr %3, align 8 82 | store i64 %4, ptr @X1, align 8 83 | %5 = load i64, ptr @PC, align 8 84 | %6 = add i64 %5, 4 85 | store i64 %6, ptr @PC, align 8 86 | ret void 87 | } 88 | 89 | declare void @capstone_call(i64) 90 | 91 | define void @capstone_return(i64 %0) { 92 | %2 = sub i64 %0, 4 93 | store i64 %2, ptr @PC, align 8 94 | ret void 95 | } 96 | 97 | define void @capstone_branch(i64 %0) { 98 | %2 = sub i64 %0, 4 99 | store i64 %2, ptr @PC, align 8 100 | ret void 101 | } 102 | 103 | define void @capstone_branch_cond(i1 %0, i64 %1) { 104 | %3 = load i64, ptr @PC, align 8 105 | %4 = sub i64 %1, 4 106 | %5 = select i1 %0, i64 %4, i64 %3 107 | store i64 %5, ptr @PC, align 8 108 | ret void 109 | } 110 | -------------------------------------------------------------------------------- /out/ldr.rem: -------------------------------------------------------------------------------- 1 | ; ModuleID = '' 2 | source_filename = "lifted_code" 3 | target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" 4 | 5 | @X0 = global i64 0 6 | @X1 = global i64 0 7 | @X2 = global i64 0 8 | @X3 = global i64 0 9 | @X4 = global i64 0 10 | @X5 = global i64 0 11 | @X6 = global i64 0 12 | @X7 = global i64 0 13 | @X8 = global i64 0 14 | @X9 = global i64 0 15 | @X10 = global i64 0 16 | @X11 = global i64 0 17 | @X12 = global i64 0 18 | @X13 = global i64 0 19 | @X14 = global i64 0 20 | @X15 = global i64 0 21 | @X16 = global i64 0 22 | @X17 = global i64 0 23 | @X18 = global i64 0 24 | @X19 = global i64 0 25 | @X20 = global i64 0 26 | @X21 = global i64 0 27 | @X22 = global i64 0 28 | @X23 = global i64 0 29 | @X24 = global i64 0 30 | @X25 = global i64 0 31 | @X26 = global i64 0 32 | @X27 = global i64 0 33 | @X28 = global i64 0 34 | @X29 = global i64 0 35 | @X30 = global i64 0 36 | @X31 = global i64 0 37 | @V0 = global i128 0 38 | @V1 = global i128 0 39 | @V2 = global i128 0 40 | @V3 = global i128 0 41 | @V4 = global i128 0 42 | @V5 = global i128 0 43 | @V6 = global i128 0 44 | @V7 = global i128 0 45 | @V8 = global i128 0 46 | @V9 = global i128 0 47 | @V10 = global i128 0 48 | @V11 = global i128 0 49 | @V12 = global i128 0 50 | @V13 = global i128 0 51 | @V14 = global i128 0 52 | @V15 = global i128 0 53 | @V16 = global i128 0 54 | @V17 = global i128 0 55 | @V18 = global i128 0 56 | @V19 = global i128 0 57 | @V20 = global i128 0 58 | @V21 = global i128 0 59 | @V22 = global i128 0 60 | @V23 = global i128 0 61 | @V24 = global i128 0 62 | @V25 = global i128 0 63 | @V26 = global i128 0 64 | @V27 = global i128 0 65 | @V28 = global i128 0 66 | @V29 = global i128 0 67 | @V30 = global i128 0 68 | @V31 = global i128 0 69 | @NF = global i1 false 70 | @ZF = global i1 false 71 | @CF = global i1 false 72 | @VF = global i1 false 73 | @PC = global i64 0 74 | 75 | ; Function Attrs: alwaysinline 76 | declare ptr @sub_0(ptr noalias, i64, ptr noalias) #0 77 | 78 | ; Function Attrs: alwaysinline mustprogress noduplicate nofree nosync nounwind readnone willreturn 79 | declare dso_local i64 @__remill_read_memory_64(ptr noundef readnone, i64 noundef) #1 80 | 81 | ; Function Attrs: alwaysinline noduplicate nounwind 82 | declare dso_local ptr @__remill_missing_block(ptr noundef nonnull align 1, i64 noundef, ptr noundef) #2 83 | 84 | define void @root() { 85 | %1 = load i64, ptr @X2, align 8 86 | %2 = load i64, ptr @X3, align 8 87 | %add.i.i = add i64 %2, %1 88 | %call.i.i = call i64 @__remill_read_memory_64(ptr noundef undef, i64 noundef %add.i.i) #3 89 | store i64 %call.i.i, ptr @X1, align 8 90 | store i64 add (i64 ptrtoint (ptr @PC to i64), i64 4), ptr @PC, align 8 91 | ret void 92 | } 93 | 94 | attributes #0 = { alwaysinline } 95 | attributes #1 = { alwaysinline mustprogress noduplicate nofree nosync nounwind readnone willreturn "frame-pointer"="none" "no-builtins" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "tune-cpu"="generic" } 96 | attributes #2 = { alwaysinline noduplicate nounwind "frame-pointer"="all" "no-builtins" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "tune-cpu"="generic" } 97 | attributes #3 = { nobuiltin nounwind readnone willreturn "no-builtins" } 98 | -------------------------------------------------------------------------------- /out/ldr2.asl: -------------------------------------------------------------------------------- 1 | ; ModuleID = 'out/ldr.asl' 2 | source_filename = "/nonexistent.ll" 3 | 4 | @X0 = internal global i64 0 5 | @X1 = internal global i64 0 6 | @X2 = internal global i64 0 7 | @X3 = internal global i64 0 8 | @X4 = internal global i64 0 9 | @X5 = internal global i64 0 10 | @X6 = internal global i64 0 11 | @X7 = internal global i64 0 12 | @X8 = internal global i64 0 13 | @X9 = internal global i64 0 14 | @X10 = internal global i64 0 15 | @X11 = internal global i64 0 16 | @X12 = internal global i64 0 17 | @X13 = internal global i64 0 18 | @X14 = internal global i64 0 19 | @X15 = internal global i64 0 20 | @X16 = internal global i64 0 21 | @X17 = internal global i64 0 22 | @X18 = internal global i64 0 23 | @X19 = internal global i64 0 24 | @X20 = internal global i64 0 25 | @X21 = internal global i64 0 26 | @X22 = internal global i64 0 27 | @X23 = internal global i64 0 28 | @X24 = internal global i64 0 29 | @X25 = internal global i64 0 30 | @X26 = internal global i64 0 31 | @X27 = internal global i64 0 32 | @X28 = internal global i64 0 33 | @X29 = internal global i64 0 34 | @X30 = internal global i64 0 35 | @X31 = internal global i64 0 36 | @V0 = internal global i128 0 37 | @V1 = internal global i128 0 38 | @V2 = internal global i128 0 39 | @V3 = internal global i128 0 40 | @V4 = internal global i128 0 41 | @V5 = internal global i128 0 42 | @V6 = internal global i128 0 43 | @V7 = internal global i128 0 44 | @V8 = internal global i128 0 45 | @V9 = internal global i128 0 46 | @V10 = internal global i128 0 47 | @V11 = internal global i128 0 48 | @V12 = internal global i128 0 49 | @V13 = internal global i128 0 50 | @V14 = internal global i128 0 51 | @V15 = internal global i128 0 52 | @V16 = internal global i128 0 53 | @V17 = internal global i128 0 54 | @V18 = internal global i128 0 55 | @V19 = internal global i128 0 56 | @V20 = internal global i128 0 57 | @V21 = internal global i128 0 58 | @V22 = internal global i128 0 59 | @V23 = internal global i128 0 60 | @V24 = internal global i128 0 61 | @V25 = internal global i128 0 62 | @V26 = internal global i128 0 63 | @V27 = internal global i128 0 64 | @V28 = internal global i128 0 65 | @V29 = internal global i128 0 66 | @V30 = internal global i128 0 67 | @V31 = internal global i128 0 68 | @NF = internal global i1 false 69 | @ZF = internal global i1 false 70 | @CF = internal global i1 false 71 | @VF = internal global i1 false 72 | @PC = internal global i64 0 73 | 74 | define void @main() { 75 | entry: 76 | %__BranchTaken = alloca i1, align 1 77 | %nRW = alloca i1, align 1 78 | %BTypeNext = alloca i2, align 1 79 | store i1 false, ptr %__BranchTaken, align 1 80 | br label %stmt 81 | 82 | stmt: ; preds = %entry 83 | %Exp9__6 = alloca i64, align 8 84 | %0 = load i64, ptr @X3, align 4 85 | store i64 %0, ptr %Exp9__6, align 4 86 | br label %stmt1 87 | 88 | stmt1: ; preds = %stmt 89 | %Exp17__5 = alloca i64, align 8 90 | %1 = load i64, ptr @X2, align 4 91 | store i64 %1, ptr %Exp17__5, align 4 92 | br label %stmt2 93 | 94 | stmt2: ; preds = %stmt1 95 | %Exp18__5 = alloca i64, align 8 96 | %2 = load i64, ptr %Exp17__5, align 4 97 | %3 = load i64, ptr %Exp9__6, align 4 98 | %4 = add i64 %2, %3 99 | %5 = inttoptr i64 %4 to ptr 100 | %6 = load i64, ptr %5, align 4 101 | store i64 %6, ptr %Exp18__5, align 4 102 | br label %stmt3 103 | 104 | stmt3: ; preds = %stmt2 105 | %7 = load i64, ptr %Exp18__5, align 4 106 | store i64 %7, ptr @X1, align 4 107 | br label %8 108 | 109 | 8: ; preds = %stmt3 110 | %9 = load i1, ptr %__BranchTaken, align 1 111 | %10 = load i64, ptr @PC, align 4 112 | %11 = add i64 %10, 4 113 | %12 = select i1 %9, i64 %10, i64 %11 114 | store i64 %12, ptr @PC, align 4 115 | ret void 116 | } 117 | -------------------------------------------------------------------------------- /out/ret.asl: -------------------------------------------------------------------------------- 1 | ; ModuleID = './lib/state.ll' 2 | source_filename = "/nonexistent.ll" 3 | 4 | @X0 = internal global i64 0 5 | @X1 = internal global i64 0 6 | @X2 = internal global i64 0 7 | @X3 = internal global i64 0 8 | @X4 = internal global i64 0 9 | @X5 = internal global i64 0 10 | @X6 = internal global i64 0 11 | @X7 = internal global i64 0 12 | @X8 = internal global i64 0 13 | @X9 = internal global i64 0 14 | @X10 = internal global i64 0 15 | @X11 = internal global i64 0 16 | @X12 = internal global i64 0 17 | @X13 = internal global i64 0 18 | @X14 = internal global i64 0 19 | @X15 = internal global i64 0 20 | @X16 = internal global i64 0 21 | @X17 = internal global i64 0 22 | @X18 = internal global i64 0 23 | @X19 = internal global i64 0 24 | @X20 = internal global i64 0 25 | @X21 = internal global i64 0 26 | @X22 = internal global i64 0 27 | @X23 = internal global i64 0 28 | @X24 = internal global i64 0 29 | @X25 = internal global i64 0 30 | @X26 = internal global i64 0 31 | @X27 = internal global i64 0 32 | @X28 = internal global i64 0 33 | @X29 = internal global i64 0 34 | @X30 = internal global i64 0 35 | @X31 = internal global i64 0 36 | @V0 = internal global i128 0 37 | @V1 = internal global i128 0 38 | @V2 = internal global i128 0 39 | @V3 = internal global i128 0 40 | @V4 = internal global i128 0 41 | @V5 = internal global i128 0 42 | @V6 = internal global i128 0 43 | @V7 = internal global i128 0 44 | @V8 = internal global i128 0 45 | @V9 = internal global i128 0 46 | @V10 = internal global i128 0 47 | @V11 = internal global i128 0 48 | @V12 = internal global i128 0 49 | @V13 = internal global i128 0 50 | @V14 = internal global i128 0 51 | @V15 = internal global i128 0 52 | @V16 = internal global i128 0 53 | @V17 = internal global i128 0 54 | @V18 = internal global i128 0 55 | @V19 = internal global i128 0 56 | @V20 = internal global i128 0 57 | @V21 = internal global i128 0 58 | @V22 = internal global i128 0 59 | @V23 = internal global i128 0 60 | @V24 = internal global i128 0 61 | @V25 = internal global i128 0 62 | @V26 = internal global i128 0 63 | @V27 = internal global i128 0 64 | @V28 = internal global i128 0 65 | @V29 = internal global i128 0 66 | @V30 = internal global i128 0 67 | @V31 = internal global i128 0 68 | @NF = internal global i1 false 69 | @ZF = internal global i1 false 70 | @CF = internal global i1 false 71 | @VF = internal global i1 false 72 | @PC = internal global i64 0 73 | 74 | define void @main() { 75 | entry: 76 | %__BranchTaken = alloca i1, align 1 77 | %nRW = alloca i1, align 1 78 | %BTypeNext = alloca i2, align 1 79 | store i1 false, ptr %__BranchTaken, align 1 80 | br label %0 81 | 82 | 0: ; preds = %entry 83 | %Exp4__5 = alloca i64, align 8 84 | %1 = load i64, ptr @X30, align 4 85 | store i64 %1, ptr %Exp4__5, align 4 86 | br label %2 87 | 88 | 2: ; preds = %0 89 | store i2 0, ptr %BTypeNext, align 1 90 | br label %3 91 | 92 | 3: ; preds = %2 93 | store i1 true, ptr %__BranchTaken, align 1 94 | br label %4 95 | 96 | 4: ; preds = %3 97 | %Exp6__6 = alloca i1, align 1 98 | %5 = load i1, ptr %nRW, align 1 99 | store i1 %5, ptr %Exp6__6, align 1 100 | br label %6 101 | 102 | 6: ; preds = %4 103 | br label %7 104 | 105 | 7: ; preds = %6 106 | %8 = load i64, ptr %Exp4__5, align 4 107 | store i64 %8, ptr @PC, align 4 108 | br label %9 109 | 110 | 9: ; preds = %7 111 | %10 = load i1, ptr %__BranchTaken, align 1 112 | %11 = load i64, ptr @PC, align 4 113 | %12 = add i64 %11, 4 114 | %13 = select i1 %10, i64 %11, i64 %12 115 | store i64 %13, ptr @PC, align 4 116 | ret void 117 | } 118 | -------------------------------------------------------------------------------- /out/ret.cap: -------------------------------------------------------------------------------- 1 | ; ModuleID = '' 2 | source_filename = "test" 3 | target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128" 4 | 5 | @X0 = global i64 0 6 | @X1 = global i64 0 7 | @X2 = global i64 0 8 | @X3 = global i64 0 9 | @X4 = global i64 0 10 | @X5 = global i64 0 11 | @X6 = global i64 0 12 | @X7 = global i64 0 13 | @X8 = global i64 0 14 | @X9 = global i64 0 15 | @X10 = global i64 0 16 | @X11 = global i64 0 17 | @X12 = global i64 0 18 | @X13 = global i64 0 19 | @X14 = global i64 0 20 | @X15 = global i64 0 21 | @X16 = global i64 0 22 | @X17 = global i64 0 23 | @X18 = global i64 0 24 | @X19 = global i64 0 25 | @X20 = global i64 0 26 | @X21 = global i64 0 27 | @X22 = global i64 0 28 | @X23 = global i64 0 29 | @X24 = global i64 0 30 | @X25 = global i64 0 31 | @X26 = global i64 0 32 | @X27 = global i64 0 33 | @X28 = global i64 0 34 | @X29 = global i64 0 35 | @X30 = global i64 0 36 | @X31 = global i64 0 37 | @V0 = global i128 0 38 | @V1 = global i128 0 39 | @V2 = global i128 0 40 | @V3 = global i128 0 41 | @V4 = global i128 0 42 | @V5 = global i128 0 43 | @V6 = global i128 0 44 | @V7 = global i128 0 45 | @V8 = global i128 0 46 | @V9 = global i128 0 47 | @V10 = global i128 0 48 | @V11 = global i128 0 49 | @V12 = global i128 0 50 | @V13 = global i128 0 51 | @V14 = global i128 0 52 | @V15 = global i128 0 53 | @V16 = global i128 0 54 | @V17 = global i128 0 55 | @V18 = global i128 0 56 | @V19 = global i128 0 57 | @V20 = global i128 0 58 | @V21 = global i128 0 59 | @V22 = global i128 0 60 | @V23 = global i128 0 61 | @V24 = global i128 0 62 | @V25 = global i128 0 63 | @V26 = global i128 0 64 | @V27 = global i128 0 65 | @V28 = global i128 0 66 | @V29 = global i128 0 67 | @V30 = global i128 0 68 | @V31 = global i128 0 69 | @NF = global i1 false 70 | @ZF = global i1 false 71 | @CF = global i1 false 72 | @VF = global i1 false 73 | @PC = global i64 0 74 | 75 | define void @root() { 76 | entry: 77 | %0 = load i64, ptr @X30, align 8 78 | store i64 %0, ptr @PC, align 8 79 | ret void 80 | } 81 | 82 | declare void @capstone_call(i64) 83 | 84 | define void @capstone_return(i64 %0) { 85 | %2 = sub i64 %0, 4 86 | store i64 %2, ptr @PC, align 8 87 | ret void 88 | } 89 | 90 | define void @capstone_branch(i64 %0) { 91 | %2 = sub i64 %0, 4 92 | store i64 %2, ptr @PC, align 8 93 | ret void 94 | } 95 | 96 | define void @capstone_branch_cond(i1 %0, i64 %1) { 97 | %3 = load i64, ptr @PC, align 8 98 | %4 = sub i64 %1, 4 99 | %5 = select i1 %0, i64 %4, i64 %3 100 | store i64 %5, ptr @PC, align 8 101 | ret void 102 | } 103 | -------------------------------------------------------------------------------- /out/ret.rem: -------------------------------------------------------------------------------- 1 | ; ModuleID = '' 2 | source_filename = "" 3 | -------------------------------------------------------------------------------- /out/ret2.rem: -------------------------------------------------------------------------------- 1 | ; ModuleID = '' 2 | source_filename = "" 3 | -------------------------------------------------------------------------------- /out/str.asl: -------------------------------------------------------------------------------- 1 | ; ModuleID = './lib/state.ll' 2 | source_filename = "/nonexistent.ll" 3 | 4 | @X0 = internal global i64 0 5 | @X1 = internal global i64 0 6 | @X2 = internal global i64 0 7 | @X3 = internal global i64 0 8 | @X4 = internal global i64 0 9 | @X5 = internal global i64 0 10 | @X6 = internal global i64 0 11 | @X7 = internal global i64 0 12 | @X8 = internal global i64 0 13 | @X9 = internal global i64 0 14 | @X10 = internal global i64 0 15 | @X11 = internal global i64 0 16 | @X12 = internal global i64 0 17 | @X13 = internal global i64 0 18 | @X14 = internal global i64 0 19 | @X15 = internal global i64 0 20 | @X16 = internal global i64 0 21 | @X17 = internal global i64 0 22 | @X18 = internal global i64 0 23 | @X19 = internal global i64 0 24 | @X20 = internal global i64 0 25 | @X21 = internal global i64 0 26 | @X22 = internal global i64 0 27 | @X23 = internal global i64 0 28 | @X24 = internal global i64 0 29 | @X25 = internal global i64 0 30 | @X26 = internal global i64 0 31 | @X27 = internal global i64 0 32 | @X28 = internal global i64 0 33 | @X29 = internal global i64 0 34 | @X30 = internal global i64 0 35 | @X31 = internal global i64 0 36 | @V0 = internal global i128 0 37 | @V1 = internal global i128 0 38 | @V2 = internal global i128 0 39 | @V3 = internal global i128 0 40 | @V4 = internal global i128 0 41 | @V5 = internal global i128 0 42 | @V6 = internal global i128 0 43 | @V7 = internal global i128 0 44 | @V8 = internal global i128 0 45 | @V9 = internal global i128 0 46 | @V10 = internal global i128 0 47 | @V11 = internal global i128 0 48 | @V12 = internal global i128 0 49 | @V13 = internal global i128 0 50 | @V14 = internal global i128 0 51 | @V15 = internal global i128 0 52 | @V16 = internal global i128 0 53 | @V17 = internal global i128 0 54 | @V18 = internal global i128 0 55 | @V19 = internal global i128 0 56 | @V20 = internal global i128 0 57 | @V21 = internal global i128 0 58 | @V22 = internal global i128 0 59 | @V23 = internal global i128 0 60 | @V24 = internal global i128 0 61 | @V25 = internal global i128 0 62 | @V26 = internal global i128 0 63 | @V27 = internal global i128 0 64 | @V28 = internal global i128 0 65 | @V29 = internal global i128 0 66 | @V30 = internal global i128 0 67 | @V31 = internal global i128 0 68 | @NF = internal global i1 false 69 | @ZF = internal global i1 false 70 | @CF = internal global i1 false 71 | @VF = internal global i1 false 72 | @PC = internal global i64 0 73 | 74 | define void @main() { 75 | entry: 76 | %__BranchTaken = alloca i1, align 1 77 | %nRW = alloca i1, align 1 78 | %BTypeNext = alloca i2, align 1 79 | store i1 false, ptr %__BranchTaken, align 1 80 | br label %stmt 81 | 82 | stmt: ; preds = %entry 83 | %Exp9__6 = alloca i64, align 8 84 | %0 = load i64, ptr @X3, align 4 85 | store i64 %0, ptr %Exp9__6, align 4 86 | br label %stmt1 87 | 88 | stmt1: ; preds = %stmt 89 | %Exp17__5 = alloca i64, align 8 90 | %1 = load i64, ptr @X2, align 4 91 | store i64 %1, ptr %Exp17__5, align 4 92 | br label %stmt2 93 | 94 | stmt2: ; preds = %stmt1 95 | %Exp19__5 = alloca i64, align 8 96 | %2 = load i64, ptr @X1, align 4 97 | store i64 %2, ptr %Exp19__5, align 4 98 | br label %stmt3 99 | 100 | stmt3: ; preds = %stmt2 101 | %3 = load i64, ptr %Exp17__5, align 4 102 | %4 = load i64, ptr %Exp9__6, align 4 103 | %5 = add i64 %3, %4 104 | %6 = load i64, ptr %Exp19__5, align 4 105 | %7 = inttoptr i64 %5 to ptr 106 | store i64 %6, ptr %7, align 4 107 | br label %8 108 | 109 | 8: ; preds = %stmt3 110 | %9 = load i1, ptr %__BranchTaken, align 1 111 | %10 = load i64, ptr @PC, align 4 112 | %11 = add i64 %10, 4 113 | %12 = select i1 %9, i64 %10, i64 %11 114 | store i64 %12, ptr @PC, align 4 115 | ret void 116 | } 117 | -------------------------------------------------------------------------------- /out/str.cap: -------------------------------------------------------------------------------- 1 | ; ModuleID = '' 2 | source_filename = "test" 3 | target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128" 4 | 5 | @X0 = global i64 0 6 | @X1 = global i64 0 7 | @X2 = global i64 0 8 | @X3 = global i64 0 9 | @X4 = global i64 0 10 | @X5 = global i64 0 11 | @X6 = global i64 0 12 | @X7 = global i64 0 13 | @X8 = global i64 0 14 | @X9 = global i64 0 15 | @X10 = global i64 0 16 | @X11 = global i64 0 17 | @X12 = global i64 0 18 | @X13 = global i64 0 19 | @X14 = global i64 0 20 | @X15 = global i64 0 21 | @X16 = global i64 0 22 | @X17 = global i64 0 23 | @X18 = global i64 0 24 | @X19 = global i64 0 25 | @X20 = global i64 0 26 | @X21 = global i64 0 27 | @X22 = global i64 0 28 | @X23 = global i64 0 29 | @X24 = global i64 0 30 | @X25 = global i64 0 31 | @X26 = global i64 0 32 | @X27 = global i64 0 33 | @X28 = global i64 0 34 | @X29 = global i64 0 35 | @X30 = global i64 0 36 | @X31 = global i64 0 37 | @V0 = global i128 0 38 | @V1 = global i128 0 39 | @V2 = global i128 0 40 | @V3 = global i128 0 41 | @V4 = global i128 0 42 | @V5 = global i128 0 43 | @V6 = global i128 0 44 | @V7 = global i128 0 45 | @V8 = global i128 0 46 | @V9 = global i128 0 47 | @V10 = global i128 0 48 | @V11 = global i128 0 49 | @V12 = global i128 0 50 | @V13 = global i128 0 51 | @V14 = global i128 0 52 | @V15 = global i128 0 53 | @V16 = global i128 0 54 | @V17 = global i128 0 55 | @V18 = global i128 0 56 | @V19 = global i128 0 57 | @V20 = global i128 0 58 | @V21 = global i128 0 59 | @V22 = global i128 0 60 | @V23 = global i128 0 61 | @V24 = global i128 0 62 | @V25 = global i128 0 63 | @V26 = global i128 0 64 | @V27 = global i128 0 65 | @V28 = global i128 0 66 | @V29 = global i128 0 67 | @V30 = global i128 0 68 | @V31 = global i128 0 69 | @NF = global i1 false 70 | @ZF = global i1 false 71 | @CF = global i1 false 72 | @VF = global i1 false 73 | @PC = global i64 0 74 | 75 | define void @root() { 76 | entry: 77 | %0 = load i64, ptr @X1, align 8 78 | %1 = load i64, ptr @X2, align 8 79 | %2 = load i64, ptr @X3, align 8 80 | %3 = add i64 %1, %2 81 | %4 = inttoptr i64 %3 to ptr 82 | store i64 %0, ptr %4, align 8 83 | %5 = load i64, ptr @PC, align 8 84 | %6 = add i64 %5, 4 85 | store i64 %6, ptr @PC, align 8 86 | ret void 87 | } 88 | 89 | declare void @capstone_call(i64) 90 | 91 | define void @capstone_return(i64 %0) { 92 | %2 = sub i64 %0, 4 93 | store i64 %2, ptr @PC, align 8 94 | ret void 95 | } 96 | 97 | define void @capstone_branch(i64 %0) { 98 | %2 = sub i64 %0, 4 99 | store i64 %2, ptr @PC, align 8 100 | ret void 101 | } 102 | 103 | define void @capstone_branch_cond(i1 %0, i64 %1) { 104 | %3 = load i64, ptr @PC, align 8 105 | %4 = sub i64 %1, 4 106 | %5 = select i1 %0, i64 %4, i64 %3 107 | store i64 %5, ptr @PC, align 8 108 | ret void 109 | } 110 | -------------------------------------------------------------------------------- /src/asl.cpp: -------------------------------------------------------------------------------- 1 | #include "context.h" 2 | #include "state.h" 3 | #include "translate.h" 4 | 5 | #include 6 | 7 | void asl(Module& m) { 8 | std::vector globals; 9 | for (auto& glo : m.globals()) 10 | globals.push_back(&glo); 11 | 12 | correctGlobalAccesses(globals); 13 | Function* root = findFunction(m, "root"); 14 | assert(root && "failed to find root function in asl"); 15 | correctMemoryAccesses(m, *root); 16 | } 17 | -------------------------------------------------------------------------------- /src/capstone.cpp: -------------------------------------------------------------------------------- 1 | #include "context.h" 2 | #include "state.h" 3 | #include "llvm/IR/IRBuilder.h" 4 | #include "llvm/IR/Type.h" 5 | #include "llvm/Support/TypeSize.h" 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | /** 12 | * Translation rules for retdec's capstone2llvmir tool. 13 | * 14 | * This uses a flattened list of all registers inside 15 | * the state. 16 | * Notably, register aliases are repeated separately instead 17 | * of aliasing properly. 18 | * 19 | * Memory load/store is done directly by casting the address 20 | * to a pointer and dereferencing that pointer. 21 | */ 22 | 23 | std::optional discriminateGlobal(std::string nm) { 24 | if (nm.size() == 0) { 25 | return std::nullopt; 26 | } 27 | char first = nm.at(0); 28 | 29 | std::string vectorRegs = "vqds"; 30 | if ((first == 'x' )&& nm.size() <= 3) { 31 | return StateReg{X, std::stoi(nm.substr(1))}; 32 | } else if (nm == "pc") { 33 | return StateReg{PC}; 34 | } else if (nm == "sp") { 35 | return StateReg{SP}; 36 | } else if (vectorRegs.find(first) != std::string::npos && nm.size() <= 3) { 37 | return StateReg{V, std::stoi(nm.substr(1))}; 38 | } else if (nm.starts_with("cpsr_")) { 39 | return StateReg{STATUS, toupper(nm.at(5))}; 40 | } else { 41 | return std::nullopt; 42 | } 43 | } 44 | 45 | void capstoneMakeBranchCond(Module& m, GlobalVariable& pc) { 46 | Function* f2 = findFunction(m, "capstone_branch_cond"); 47 | if (f2 == NULL) return; 48 | Function& f = *f2; 49 | assert(f.arg_size() == 2); 50 | 51 | Type* ty = pc.getValueType(); 52 | auto* four = ConstantInt::get(ty, 4); 53 | 54 | using BOp = llvm::BinaryOperator; 55 | 56 | auto* bb = BasicBlock::Create(Context, "", &f); 57 | auto* load = new LoadInst(ty, &pc, "", bb); 58 | auto* dest = BOp::Create(BOp::Add, load, f.getArg(1), "", bb); 59 | auto* sel = SelectInst::Create( 60 | f.getArg(0), 61 | BOp::Create(BOp::Sub, dest, four, "", bb), 62 | load, 63 | "", bb); 64 | new StoreInst(sel, &pc, bb); 65 | ReturnInst::Create(Context, bb); 66 | } 67 | 68 | void capstoneMakeBranch(Module& m, GlobalVariable& pc) { 69 | Function* f2 = findFunction(m, "capstone_branch"); 70 | if (f2 == NULL) return; 71 | Function& f = *f2; 72 | assert(f.arg_size() == 1); 73 | 74 | auto* bb = BasicBlock::Create(Context, "", &f); 75 | auto* tru = ConstantInt::getTrue(Context); 76 | 77 | Function& cond = *findFunction(m, "capstone_branch_cond"); 78 | ArrayRef args{tru, f.getArg(0)}; 79 | CallInst::Create(cond.getFunctionType(), &cond, args, "", bb); 80 | ReturnInst::Create(Context, bb); 81 | } 82 | 83 | void capstoneMakeReturn(Module& m, GlobalVariable& pc) { 84 | Function* f2 = findFunction(m, "capstone_return"); 85 | if (f2 == NULL) return; 86 | Function& f = *f2; 87 | auto* bb = BasicBlock::Create(Context, "", &f); 88 | 89 | // a return is just a branch. 90 | Function& cond = *findFunction(m, "capstone_branch"); 91 | CallInst::Create(cond.getFunctionType(), &cond, {f.getArg(0)}, "", bb); 92 | ReturnInst::Create(Context, bb); 93 | 94 | } 95 | 96 | void capstone(Module& m) { 97 | assert(m.getFunctionList().size() > 0); 98 | 99 | for (const auto del : {"capstone_asm2llvm", "0"}) { 100 | if (auto* capVar = m.getNamedGlobal(del)) { 101 | for (auto* user : clone_it(capVar->users())) { 102 | if (auto* inst = dyn_cast(user)) { 103 | errs() << "deleting: " << *inst << '\n'; 104 | assert(inst->isSafeToRemove()); 105 | inst->eraseFromParent(); 106 | } 107 | } 108 | assert(capVar->getNumUses() == 0); 109 | capVar->eraseFromParent(); 110 | } 111 | } 112 | 113 | Function& f = *m.begin(); 114 | f.setName(entry_function_name); 115 | // BasicBlock& entry = newEntryBlock(f); 116 | assert(!f.empty() && "function empty"); 117 | 118 | ReturnInst* back = &uniqueReturn(f); 119 | 120 | auto capstone = internaliseGlobals(m, f); 121 | auto unified = generateGlobalState(m, f); 122 | 123 | // here, cap refers to the capstone-specific variable 124 | // glo is the allocated global 125 | // reg is the abstract description 126 | 127 | for (auto* cap : capstone) { 128 | if (cap->user_empty()) { 129 | // errs() << "erased unused capstone: " << *cap << '\n'; 130 | cap->eraseFromParent(); 131 | continue; 132 | } 133 | std::string nm = cap->getName().str(); 134 | auto stateOpt = discriminateGlobal(nm); 135 | if (stateOpt.has_value()) { 136 | // capstone variable is exactly a unified register. 137 | // replace all uses directly. 138 | StateReg reg = *stateOpt; 139 | auto nm = reg.name(); 140 | Type* ty = reg.ty(); 141 | 142 | GlobalVariable* glo = m.getNamedGlobal(nm); 143 | assert(glo != nullptr && "unified global variable not found"); 144 | 145 | assert(glo->getValueType() == ty); 146 | if (cap->getAllocatedType() != ty) { 147 | auto size = cap->getAllocatedType()->getPrimitiveSizeInBits().getFixedSize(); 148 | Type* capIntTy = IntegerType::get(Context, size); 149 | for (auto* use : cap->users()) { 150 | if (auto* load = dyn_cast(use)) { 151 | IRBuilder irb{load}; 152 | auto* load2 = irb.CreateLoad(capIntTy, glo); 153 | auto* cast = irb.CreateBitCast(load2, cap->getAllocatedType()); 154 | load->replaceAllUsesWith(cast); 155 | } else if (auto* stor = dyn_cast(use)) { 156 | IRBuilder irb{stor}; 157 | auto* cast = irb.CreateBitCast(stor->getValueOperand(), capIntTy); 158 | auto* stor2 = irb.CreateStore(cast, glo); 159 | stor->replaceAllUsesWith(stor2); 160 | } else { 161 | errs() << *use << '\n'; 162 | assert(false && "unsupported use of capstone alias register"); 163 | } 164 | 165 | } 166 | } else { 167 | cap->replaceAllUsesWith(glo); 168 | } 169 | } else if (!cap->hasName() && cap->getNumUses() <= 1) { 170 | // eliminate: store volatile i64 0, i64* @0 171 | for (auto* use : clone_it(cap->users())) { 172 | if (auto* inst = dyn_cast(use)) { 173 | assert(inst->isSafeToRemove()); 174 | inst->eraseFromParent(); 175 | } 176 | } 177 | assert(cap->getNumUses() == 0); 178 | } else { 179 | errs() << *cap << "\n"; 180 | assert(0 && "unhandled capstone variable"); 181 | } 182 | } 183 | 184 | 185 | GlobalVariable* pc = m.getNamedGlobal("PC"); 186 | assert(pc); 187 | Type* ty = pc->getValueType(); 188 | auto* load = new LoadInst(ty, pc, "", back); 189 | auto* four = ConstantInt::get(ty, 4); 190 | auto* inc = BinaryOperator::Create( 191 | Instruction::BinaryOps::Add, load, four, "", back); 192 | new StoreInst(inc, pc, back); 193 | 194 | 195 | capstoneMakeBranchCond(m, *pc); 196 | capstoneMakeBranch(m, *pc); 197 | capstoneMakeReturn(m, *pc); 198 | 199 | correctGlobalAccesses(unified); 200 | correctMemoryAccesses(m, f); 201 | } 202 | -------------------------------------------------------------------------------- /src/context.cpp: -------------------------------------------------------------------------------- 1 | #include "context.h" 2 | 3 | llvm::LLVMContext Context{}; 4 | -------------------------------------------------------------------------------- /src/context.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "llvm/IR/LLVMContext.h" 4 | 5 | #define assertm(exp, msg) assert(((void)msg, exp)) 6 | 7 | 8 | extern llvm::LLVMContext Context; 9 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | #include "llvm/IR/Module.h" 9 | #include "llvm/IR/IRBuilder.h" 10 | #include "llvm/IR/Verifier.h" 11 | #include "llvm/IRReader/IRReader.h" 12 | 13 | #include "llvm/Support/raw_ostream.h" 14 | #include "llvm/Support/SourceMgr.h" 15 | 16 | 17 | #include "context.h" 18 | #include "state.h" 19 | #include "translate.h" 20 | 21 | using namespace llvm; 22 | 23 | const char *__asan_default_options() { 24 | return "disable_coredump=0"; 25 | } 26 | 27 | int force_vars(std::vector& argv) { 28 | std::map globals; 29 | std::map loads; 30 | std::map> Modules; 31 | 32 | auto fnames = std::ranges::subrange(argv.begin() + 2, argv.end()); 33 | 34 | for (auto& fname : fnames) { 35 | SMDiagnostic Err{}; 36 | auto Module = parseIRFile(fname, Err, Context); 37 | assert(Module && "failed to parse module"); 38 | Modules[fname] = std::move(Module); 39 | } 40 | 41 | for (auto& [_, Module] : Modules) { 42 | for (auto& var : Module->getGlobalList()) { 43 | if (var.hasNUsesOrMore(1)) { 44 | std::string name{var.getName()}; 45 | globals[name] = var.getValueType(); 46 | } 47 | } 48 | 49 | for (auto& fn : Module->getFunctionList()) { 50 | if (fn.getName().startswith("load_") && fn.hasNUsesOrMore(1)) { 51 | std::string name{fn.getName()}; 52 | loads[name] = fn.getReturnType(); 53 | } 54 | } 55 | } 56 | 57 | for (auto& [fname, Module] : Modules) { 58 | auto* root = findFunction(*Module, "root"); 59 | 60 | if (root) { 61 | auto* entry = &root->getEntryBlock(); 62 | 63 | if (entry->getName() != "forced_vars") { 64 | auto* entry2 = BasicBlock::Create(Context, "forced_vars", root, entry); 65 | 66 | IRBuilder irb{entry2, entry2->begin()}; 67 | for (auto& [nm, ty] : globals) { 68 | auto* glo = Module->getNamedGlobal(nm); 69 | auto* load = irb.CreateLoad(ty, glo, "_" + nm); 70 | noundef(load); 71 | } 72 | irb.CreateBr(entry); 73 | } 74 | } 75 | 76 | std::vector globals; 77 | for (auto& glo : Module->getGlobalList()) { 78 | globals.push_back(&glo); 79 | } 80 | correctGlobalAccesses(globals); 81 | 82 | bool err = verifyModule(*Module, &errs()); 83 | assert(!err && "verify module failed"); 84 | 85 | std::error_code Err; 86 | llvm::raw_fd_ostream file{fname, Err}; 87 | file << *Module; 88 | } 89 | 90 | return 0; 91 | } 92 | 93 | 94 | 95 | int main(int argc, char** argv) 96 | { 97 | std::vector args{argv, argv + argc}; 98 | 99 | std::string lifter {argc >= 2 ? argv[1] : ""}; 100 | const char* fname = argc >= 3 ? argv[2] : "/dev/stdin"; 101 | 102 | Context.enableOpaquePointers(); // llvm 14 specific 103 | 104 | std::function translator{}; 105 | 106 | if (lifter == "cap") { 107 | translator = capstone; 108 | } else if (lifter == "rem") { 109 | translator = remill; 110 | } else if (lifter == "asl") { 111 | translator = asl; 112 | } else if (lifter == "vars") { 113 | return force_vars(args); 114 | } else { 115 | errs() << "unsupported lifter, expected cap or rem or asl.\n"; 116 | return 1; 117 | } 118 | 119 | 120 | SMDiagnostic Err{}; 121 | errs() << "loading IR file " << fname << '\n'; 122 | std::unique_ptr ModPtr = parseIRFile(fname, Err, Context); 123 | if (!ModPtr) { 124 | Err.print(argv[0], errs()); 125 | return 1; 126 | } 127 | Module& Mod = *ModPtr; 128 | Mod.setSourceFileName(fname); 129 | 130 | auto& funcs = Mod.getFunctionList(); 131 | assert(funcs.size() >= 1); 132 | 133 | assert(translator); 134 | translator(Mod); 135 | 136 | outs() << Mod; 137 | 138 | bool err = verifyModule(Mod, &errs()); 139 | if (err) { 140 | errs() << "\n### MODULE VERIFY FAILED ###\n"; 141 | return -1; 142 | } 143 | return 0; 144 | } 145 | -------------------------------------------------------------------------------- /src/remill.cpp: -------------------------------------------------------------------------------- 1 | #include "context.h" 2 | #include "state.h" 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | StateReg translateStateAccess(Module& m, GetElementPtrInst& gep) { 13 | std::vector indices; 14 | for (auto& v : gep.indices()) { 15 | ConstantInt* c = cast(v); 16 | indices.push_back(c->getValue().getSExtValue()); 17 | } 18 | 19 | auto matches = [&](std::initializer_list prefix = {}, std::initializer_list suffix = {}) { 20 | assert(prefix.size() <= indices.size()); 21 | assert(suffix.size() <= indices.size()); 22 | 23 | for (ulong i = 0; i < prefix.size(); i++) { 24 | if (prefix.begin()[i] != indices[i]) 25 | return false; 26 | } 27 | 28 | for (ulong i = 0; i < suffix.size(); i++) { 29 | if (suffix.end()[-i-1] != indices.end()[-i-1]) 30 | return false; 31 | } 32 | 33 | return true; 34 | }; 35 | 36 | int len = indices.size(); 37 | if (len == 6 && matches({0,0,3}, {0,0})) { 38 | 39 | int k = indices.at(3); 40 | if (k == 65) 41 | return StateReg{PC}; 42 | else if (k == 63) 43 | return StateReg{SP}; 44 | else if (0 <= k && k <= 61 && k % 2 == 1) 45 | return StateReg{X, k/2}; 46 | 47 | } else if (len == 4 && matches({0,0,9}, {})) { 48 | 49 | int k = indices.at(3); 50 | if (5 <= k && k <= 11 && k % 2 == 1) { 51 | int i = (k-5) / 2; 52 | char flags[] = {'N','Z','C','V'}; 53 | return StateReg{STATUS, flags[i]}; 54 | } 55 | 56 | } else if (len == 8 && matches({0,0,1,0}, {0,0,0})) { 57 | int k = indices.at(4); 58 | return StateReg{V, k}; 59 | } 60 | 61 | errs() << "failed: " << gep << '\n'; 62 | assert(false && "unhandled state getelementptr"); 63 | } 64 | 65 | 66 | void replaceRemillStateAccess(Module& m, Function& f) { 67 | assert(f.arg_size() == 3 && f.getArg(0)->getName() == "state"); 68 | 69 | auto& entry = f.getEntryBlock(); 70 | auto* state = f.getArg(0); 71 | auto* pc = f.getArg(1); 72 | auto* mem = f.getArg(2); 73 | 74 | for (User* u : clone_it(state->users())) { 75 | if (auto* gep = dyn_cast(u)) { 76 | StateReg reg = translateStateAccess(m, *gep); 77 | GlobalVariable* glo = m.getNamedGlobal(reg.name()); 78 | gep->replaceAllUsesWith(glo); 79 | 80 | assert(gep->isSafeToRemove()); 81 | gep->eraseFromParent(); 82 | 83 | } else if (auto* store = dyn_cast(u); store && store->getValueOperand() == state) { 84 | // remill inserts a superfluous store of %state into %STATE: 85 | // %STATE = alloca ptr, align 8 86 | // store ptr %state, ptr %STATE, align 8 87 | 88 | // get alloc of %STATE 89 | auto* alloc = cast(store->getPointerOperand()); 90 | 91 | assert(store->isSafeToRemove()); 92 | store->eraseFromParent(); 93 | 94 | assert(alloc->isSafeToRemove()); 95 | alloc->eraseFromParent(); 96 | } else if (ConstantInt* val; store && store->getPointerOperand() == state 97 | && (val = dyn_cast(store->getValueOperand())) 98 | && val->equalsInt(32)) { 99 | // eliminate: store i32 32, ptr %state, align 16 100 | assert(store->isSafeToRemove()); 101 | store->eraseFromParent(); 102 | } else { 103 | if (auto call = dyn_cast(u)) { 104 | // remill-style branch: call ptr @sub_fffffffffffffffc(ptr %state, i64 %10, ptr %9) 105 | if (call->getNumUses() == 0 && call->getCalledFunction()->getName().startswith("sub_")) { 106 | // at this point, the call address is in PC and the return address is in %RETURN_PC and @X30 107 | auto* pc = m.getNamedGlobal("PC"); 108 | auto* load = new LoadInst(pc->getValueType(), pc, "", call); 109 | auto* return_pc = findLocalVariable(f, "RETURN_PC"); 110 | auto* store = new StoreInst(load, return_pc, call); 111 | // the function epilogue moves %RETURN_PC into @PC which overwrites the branch address. 112 | // this alters %RETURN_PC so @PC value is the branch address at end of function. 113 | 114 | call->eraseFromParent(); 115 | continue; 116 | } 117 | } 118 | errs() << *u << '\n'; 119 | assert(false && "unsupported user of remill state"); 120 | } 121 | } 122 | 123 | auto* globalpc = m.getNamedGlobal(StateReg{PC}.name()); 124 | // remill has a %program_counter argument which is just the initial program counter. 125 | auto* pcload = new LoadInst( 126 | pc->getType(), globalpc, "program_counter", &*entry.getFirstInsertionPt()); 127 | noundef(pcload); 128 | pc->replaceAllUsesWith(pcload); 129 | assert(pc->getNumUses() == 0); 130 | 131 | mem->replaceAllUsesWith(UndefValue::get(mem->getType())); 132 | 133 | // for (auto* u : clone_it(mem->users())) { 134 | // if (auto* inst = dyn_cast(u)) { 135 | // inst->eraseFromParent(); 136 | // } 137 | // } 138 | 139 | // for (Instruction& inst : f.getEntryBlock()) { 140 | // AllocaInst* alloc; 141 | // if ((alloc = dyn_cast(&inst)) && inst.getName() == "MEMORY") { 142 | 143 | // for (User* u : clone_it(alloc->users())) { 144 | // cast(u)->eraseFromParent(); 145 | // } 146 | 147 | // } 148 | 149 | // } 150 | 151 | } 152 | 153 | void replaceRemillTailCall(Module& m, Function& f) { 154 | assert(!findFunction(m, "__remill_error") && "opcode unsupported in remill"); 155 | Function* missing_block = findFunction(m, "__remill_missing_block"); 156 | if (!missing_block) { 157 | missing_block = findFunction(m, "__remill_error"); 158 | } 159 | if (!missing_block) { 160 | missing_block = findFunction(m, "__remill_function_return"); 161 | } 162 | if (!missing_block) { 163 | missing_block = findFunction(m, "__remill_jump"); // br 164 | } 165 | assert(missing_block); 166 | 167 | // ReturnInst::Create(Context, UndefValue::get(PointerType::get(Context, 0)), 168 | // BasicBlock::Create(Context, "", &missing_block)); 169 | // assert(missing_block->getNumUses() == 1); 170 | for (User * user : clone_it(missing_block->users())) { 171 | if (auto* call = dyn_cast(user)) { 172 | call->replaceAllUsesWith(UndefValue::get(call->getType())); 173 | call->eraseFromParent(); 174 | } 175 | } 176 | 177 | // assert(call->getNumUses() == 1); 178 | 179 | for (ReturnInst& ret : functionReturns(f)) { 180 | ret.replaceAllUsesWith(ReturnInst::Create(Context, nullptr, &ret)); 181 | ret.eraseFromParent(); 182 | } 183 | } 184 | 185 | void replaceRemillMemory(Module& m, Function& f) { 186 | std::initializer_list sizes = { 8, 16, 32, 64 }; 187 | 188 | for (int sz : sizes) { 189 | std::string name = "__remill_read_memory_" + std::to_string(sz); 190 | Function* fn = findFunction(m, name); 191 | if (!fn) continue; 192 | 193 | for (User* u : clone_it(fn->users())) { 194 | CallInst* call = cast(u); 195 | Value* addr = call->getArgOperand(1); 196 | 197 | IntToPtrInst* int2ptr = new IntToPtrInst(addr, PointerType::get(Context, 0), "", call); 198 | LoadInst* load = new LoadInst(call->getType(), int2ptr, "", call); 199 | noundef(load); 200 | 201 | call->replaceAllUsesWith(load); 202 | call->eraseFromParent(); 203 | } 204 | } 205 | 206 | for (int sz : sizes) { 207 | std::string name = "__remill_write_memory_" + std::to_string(sz); 208 | Function* fn = findFunction(m, name); 209 | if (!fn) continue; 210 | 211 | for (User* u : clone_it(fn->users())) { 212 | CallInst* call = cast(u); 213 | Value* addr = call->getArgOperand(1); 214 | Value* val = call->getArgOperand(2); 215 | 216 | IntToPtrInst* int2ptr = new IntToPtrInst(addr, PointerType::get(Context, 0), "", call); 217 | StoreInst* stor = new StoreInst(val, int2ptr, call); 218 | 219 | call->replaceAllUsesWith(PoisonValue::get(call->getType())); 220 | call->eraseFromParent(); 221 | } 222 | } 223 | } 224 | 225 | Function* replaceRemillFunctionSignature(Module& m, Function& f) { 226 | std::vector blocks; 227 | for (auto& bb : f) { 228 | blocks.push_back(&bb); 229 | } 230 | 231 | Function* f2 = Function::Create( 232 | FunctionType::get(Type::getVoidTy(Context), false), 233 | f.getLinkage(), entry_function_name, m 234 | ); 235 | 236 | for (auto* bb : blocks) { 237 | bb->removeFromParent(); 238 | bb->insertInto(f2); 239 | } 240 | 241 | // f.eraseFromParent(); 242 | 243 | return f2; 244 | } 245 | 246 | void remill(Module& m) { 247 | m.setTargetTriple(""); 248 | 249 | std::vector flag_funcs = { 250 | "__remill_flag_computation_sign", 251 | "__remill_flag_computation_zero", 252 | "__remill_flag_computation_overflow", 253 | "__remill_flag_computation_carry", 254 | "__remill_compare_sle", 255 | "__remill_compare_slt", 256 | "__remill_compare_sgt", 257 | "__remill_compare_sge", 258 | "__remill_compare_eq", 259 | "__remill_compare_neq", 260 | "__remill_compare_ugt", 261 | "__remill_compare_uge", 262 | "__remill_compare_ult", 263 | "__remill_compare_ule", 264 | }; 265 | 266 | for (auto& nm : flag_funcs) { 267 | Function* f = findFunction(m, nm); 268 | if (!f) continue; 269 | for (auto* u : clone_it(f->users())) { 270 | // errs() << "USER: " << *u << '\n'; 271 | if (auto* call = dyn_cast(u)) { 272 | call->replaceAllUsesWith(call->getArgOperand(0)); 273 | call->eraseFromParent(); 274 | } 275 | } 276 | } 277 | 278 | 279 | for (auto& f : m.functions()) { 280 | f.removeFnAttr(Attribute::AttrKind::OptimizeNone); 281 | f.removeFnAttr(Attribute::AttrKind::NoInline); 282 | f.addFnAttr(Attribute::get(Context, Attribute::AttrKind::AlwaysInline)); 283 | } 284 | 285 | Function* root = findFunction(m, "sub_0"); 286 | assert(root && "remill missing sub_0"); 287 | 288 | auto globals = generateGlobalState(m, *root); 289 | 290 | replaceRemillTailCall(m, *root); 291 | replaceRemillStateAccess(m, *root); 292 | replaceRemillMemory(m, *root); 293 | 294 | correctMemoryAccesses(m, *root); 295 | correctGlobalAccesses(globals); 296 | 297 | root = replaceRemillFunctionSignature(m, *root); 298 | } 299 | -------------------------------------------------------------------------------- /src/state.cpp: -------------------------------------------------------------------------------- 1 | #include "state.h" 2 | #include "context.h" 3 | 4 | #include "llvm/IR/IRBuilder.h" 5 | #include "llvm/IR/Instructions.h" 6 | #include "llvm/Support/Casting.h" 7 | 8 | #include 9 | 10 | using namespace llvm; 11 | 12 | const std::string entry_function_name = "root"; 13 | 14 | static constexpr int XS_COUNT = 32; 15 | static constexpr int XS_SIZE = 64; 16 | static constexpr int VS_COUNT = 32; 17 | static constexpr int VS_SIZE = 128; 18 | 19 | Function* findFunction(Module& m, std::string const& name) { 20 | auto it = std::find_if(m.begin(), m.end(), 21 | [&name](Function& f) { return f.getName() == name; }); 22 | // assert((it != m.end() || (errs() << name, 0)) 23 | // && "unable to find function matching name"); 24 | return it != m.end() ? &*it : nullptr; 25 | } 26 | 27 | AllocaInst* findLocalVariable(Function& f, std::string const& name) { 28 | for (auto& bb : f) { 29 | for (auto& inst : bb) { 30 | if (auto* alloc = dyn_cast(&inst)) { 31 | if (alloc->getName() == name) 32 | return alloc; 33 | } 34 | } 35 | } 36 | return nullptr; 37 | } 38 | 39 | GlobalVariable* variable(Module& m, int size, const std::string nm) { 40 | IntegerType* ty = Type::getIntNTy(Context, size); 41 | 42 | Constant* val = ConstantInt::get(ty, 0); 43 | 44 | return new GlobalVariable(m, 45 | ty, false, GlobalValue::LinkageTypes::ExternalLinkage, 46 | val, nm); 47 | } 48 | 49 | std::vector generateGlobalState(Module& m, Function& f) { 50 | 51 | std::vector regs{}; 52 | 53 | for (int i = 0; i < XS_COUNT; i++) { 54 | regs.push_back({X, i}); 55 | } 56 | for (int i = 0; i < VS_COUNT; i++) { 57 | regs.push_back({V, i}); 58 | } 59 | 60 | regs.push_back({STATUS, 'N'}); 61 | regs.push_back({STATUS, 'Z'}); 62 | regs.push_back({STATUS, 'C'}); 63 | regs.push_back({STATUS, 'V'}); 64 | 65 | regs.push_back({PC}); 66 | regs.push_back({SP}); 67 | 68 | std::vector globals{}; 69 | for (auto& reg : regs) { 70 | globals.push_back(variable(m, reg.size(), reg.name())); 71 | } 72 | 73 | return globals; 74 | } 75 | 76 | void noundef(LoadInst* load) { 77 | assert(load); 78 | load->setMetadata("noundef", MDTuple::get(Context, {})); 79 | } 80 | 81 | void correctGetElementPtr(GlobalVariable* glo, User* gep, int offset) { 82 | Type* gloTy = glo->getValueType(); 83 | 84 | for (User* u2 : clone_it(gep->users())) { 85 | if (auto* load = dyn_cast(u2)) { 86 | IRBuilder irb{load}; 87 | auto* load2 = irb.CreateLoad(gloTy, glo, ""); 88 | auto* shift = offset > 0 ? irb.CreateLShr(load2, offset) : load2; 89 | auto* trunc = irb.CreateTruncOrBitCast(shift, load->getType()); 90 | load->replaceAllUsesWith(trunc); 91 | load->eraseFromParent(); 92 | } else if (auto* store = dyn_cast(u2)) { 93 | IRBuilder irb{store}; 94 | 95 | auto* value = store->getValueOperand(); 96 | auto* valueTy = value->getType(); 97 | value = irb.CreateZExtOrBitCast(value, gloTy); 98 | value = offset > 0 ? irb.CreateShl(value, offset) : value; 99 | 100 | auto* load2 = irb.CreateLoad(gloTy, glo, ""); 101 | auto focus = APInt::getZero(valueTy->getIntegerBitWidth()); 102 | auto mask = APInt::getAllOnes(gloTy->getIntegerBitWidth()); 103 | mask.insertBits(focus, offset); 104 | 105 | auto* andd = irb.CreateAnd(load2, ConstantInt::get(gloTy, mask)); 106 | auto* orr = irb.CreateOr(andd, value); 107 | store->replaceAllUsesWith(irb.CreateStore(orr, glo)); 108 | store->eraseFromParent(); 109 | } else { 110 | errs() << *u2 << '\n'; 111 | assert(false && "unsupported use of getelementptr of global register"); 112 | } 113 | } 114 | assert(gep->getNumUses() == 0 && "uses of gep not fully eliminated"); 115 | } 116 | 117 | 118 | void correctGlobalAccesses(const std::vector& globals) { 119 | for (auto* glo : globals) { 120 | auto* gloTy = glo->getValueType(); 121 | auto gloWd = gloTy->getIntegerBitWidth(); 122 | for (User* u : clone_it(glo->users())) { 123 | if (auto* load = dyn_cast(u)) { 124 | auto* valTy = load->getType(); 125 | unsigned valWd = valTy->getPrimitiveSizeInBits(); 126 | 127 | 128 | if (valWd == gloWd) { 129 | // width matches 130 | } else if (valWd < gloWd) { 131 | auto* next = load->getNextNode(); 132 | auto* load2 = new LoadInst(gloTy, glo, "", next); 133 | auto* trunc = new TruncInst(load2, valTy, "", next); 134 | load->replaceAllUsesWith(trunc); 135 | load = load2; 136 | } else { 137 | auto* load2 = new LoadInst(gloTy, glo, "", load); 138 | auto* ext = new ZExtInst(load2, load->getType(), "", load); 139 | load->replaceAllUsesWith(ext); 140 | load = load2; 141 | // errs() << *load << " <- " << *glo << '\n'; 142 | // assert(valWd == gloWd && "attempt to load a value from a smaller register"); 143 | } 144 | 145 | if (!load->getName().startswith("_")) { 146 | load->setName(glo->getName()); 147 | } 148 | noundef(load); 149 | } else if (auto* store = dyn_cast(u)) { 150 | auto* val = store->getValueOperand(); 151 | auto* valTy = val->getType(); 152 | unsigned valWd = valTy->getPrimitiveSizeInBits(); 153 | 154 | if (store->getAlign().value() > 8) { 155 | store->setAlignment(llvm::Align(8)); 156 | } 157 | 158 | if (valWd == gloWd) { 159 | // widths match 160 | } else if (valWd > gloWd) { 161 | store->setOperand(0, new TruncInst(val, gloTy, "", store)); 162 | } else if (valWd < gloWd) { 163 | store->setOperand(0, new ZExtInst(val, gloTy, "", store)); 164 | } 165 | } else if (auto* gep = dyn_cast(u)) { 166 | assert(gep->getNumIndices() == 1 && "too many indices for global register getelementptr"); 167 | int wd = gep->getResultElementType()->getPrimitiveSizeInBits(); 168 | int index = cast(gep->idx_begin())->getSExtValue(); 169 | correctGetElementPtr(glo, gep, wd*index); 170 | } else if (auto* gep2 = dyn_cast(u)) { 171 | assert(gep2->getNumIndices() == 1 && "too many indices for global register getelementptr"); 172 | int wd = gep2->getResultElementType()->getPrimitiveSizeInBits(); 173 | int index = cast(gep2->idx_begin())->getSExtValue(); 174 | correctGetElementPtr(glo, gep2, wd*index); 175 | } else if (auto* phi = dyn_cast(u)) { 176 | // ignore for now 177 | } else { 178 | errs() << *u << '\n'; 179 | assert(false && "unsupported use of unified global variable"); 180 | } 181 | } 182 | } 183 | } 184 | 185 | void correctMemoryAccesses(Module& m, Function& root) { 186 | std::initializer_list sizes = { 8, 16, 32, 64 }; 187 | 188 | std::map loads; 189 | std::map stores; 190 | 191 | for (int sz : sizes) { 192 | std::string loadName = "load_" + std::to_string(sz); 193 | std::string storeName = "store_" + std::to_string(sz); 194 | 195 | Type* i64 = IntegerType::get(Context, 64); 196 | Type* valTy = IntegerType::get(Context, sz); 197 | FunctionType* loadTy = FunctionType::get(valTy, {i64}, false); 198 | FunctionType* storeTy = FunctionType::get(Type::getVoidTy(Context), {i64, valTy}, false); 199 | 200 | Function* load = Function::Create(loadTy, 201 | GlobalValue::LinkageTypes::ExternalLinkage, 0, loadName, &m); 202 | Function* store = Function::Create(storeTy, 203 | GlobalValue::LinkageTypes::ExternalLinkage, 0, storeName, &m); 204 | 205 | for (Function* fn : {load, store}) { 206 | using enum Attribute::AttrKind; 207 | auto attr = [](Attribute::AttrKind kind) { 208 | return Attribute::get(Context, kind); 209 | }; 210 | 211 | fn->addParamAttr(0, attr(NoUndef)); 212 | if (!fn->getReturnType()->isVoidTy()) { 213 | // fn->addRetAttr(attr(NoUndef)); 214 | } 215 | fn->addFnAttr(attr(InaccessibleMemOnly)); 216 | if (fn == load) { 217 | fn->addFnAttr(attr(ReadOnly)); 218 | } 219 | fn->addFnAttr(attr(WillReturn)); 220 | fn->addFnAttr(attr(NoUnwind)); 221 | } 222 | 223 | loads[sz] = load; 224 | stores[sz] = store; 225 | } 226 | 227 | for (BasicBlock& bb : root) for (Instruction& inst : bb) { 228 | IntToPtrInst* i2p = dyn_cast(&inst); 229 | if (!i2p) continue; 230 | for (User* u : clone_it(i2p->users())) { 231 | auto* addr = i2p->getOperand(0); 232 | if (auto* load = dyn_cast(u)) { 233 | 234 | int sz = load->getType()->getIntegerBitWidth(); 235 | CallInst* call = CallInst::Create(loads[sz]->getFunctionType(), loads.at(sz), {addr}, "", load); 236 | load->replaceAllUsesWith(call); 237 | load->eraseFromParent(); 238 | 239 | } else if (auto* stor = dyn_cast(u)) { 240 | auto* val = stor->getValueOperand(); 241 | int sz = stor->getValueOperand()->getType()->getIntegerBitWidth(); 242 | CallInst* call = CallInst::Create(stores[sz]->getFunctionType(), stores.at(sz), {addr, val}, "", stor); 243 | stor->replaceAllUsesWith(call); 244 | stor->eraseFromParent(); 245 | 246 | } else { 247 | errs() << *u << '\n'; 248 | assert(0 && "unsupported use of int2ptr cast"); 249 | } 250 | } 251 | 252 | assert(i2p->isSafeToRemove() && "unable to remove i2p instruction"); 253 | } 254 | } 255 | 256 | 257 | BasicBlock& newEntryBlock(Function& f) { 258 | assertm(!f.empty(), "analysed function must not be empty"); 259 | BasicBlock* oldEntry = f.empty() ? nullptr : &f.getEntryBlock(); 260 | BasicBlock* newEntry = BasicBlock::Create(Context, "new_entry", &f, oldEntry); 261 | if (oldEntry) { 262 | BranchInst::Create(oldEntry, newEntry); 263 | } 264 | return f.getEntryBlock(); 265 | } 266 | 267 | std::vector internaliseGlobals(Module& module, Function& f) { 268 | 269 | Instruction& insertion = *f.getEntryBlock().getFirstInsertionPt(); 270 | 271 | std::vector allocs{}; 272 | 273 | for (auto& g : module.getGlobalList()) { 274 | 275 | auto alloc = new AllocaInst( 276 | g.getInitializer()->getType(), /*addrspace*/0, /*arraysize*/nullptr, 277 | "" + g.getName(), &insertion); 278 | allocs.push_back(alloc); 279 | 280 | g.replaceAllUsesWith(alloc); 281 | } 282 | 283 | module.getGlobalList().clear(); 284 | 285 | return allocs; 286 | } 287 | 288 | std::vector internaliseParams(Function& f) { 289 | Instruction& insertion = *f.getEntryBlock().getFirstInsertionPt(); 290 | 291 | std::vector allocs{}; 292 | 293 | for (auto& a : f.args()) { 294 | 295 | auto alloc = new AllocaInst( 296 | a.getType(), /*addrspace*/0, /*arraysize*/nullptr, 297 | "" + a.getName(), &insertion); 298 | 299 | allocs.push_back(alloc); 300 | a.replaceAllUsesWith(alloc); 301 | } 302 | 303 | return allocs; 304 | } 305 | 306 | std::vector> functionReturns(Function& f) { 307 | std::vector> rets{}; 308 | for (auto& b : f) { 309 | for (auto& i : b) { 310 | if (auto* r = dyn_cast(&i)) { 311 | rets.push_back(*r); 312 | } 313 | } 314 | } 315 | 316 | return rets; 317 | } 318 | 319 | ReturnInst& uniqueReturn(Function& f) { 320 | auto rets = functionReturns(f); 321 | assert(rets.size() > 0 && "no returns in function"); 322 | assert(rets.size() == 1 && "multiple returns in function"); 323 | return rets[0]; 324 | } 325 | 326 | std::string StateReg::name() const { 327 | std::string prefix; 328 | std::string suffix; 329 | auto t = this->type; 330 | auto d = this->data; 331 | 332 | if (t == X) { 333 | prefix = "X"; 334 | suffix = std::to_string(d.num); 335 | } else if (t == V) { 336 | prefix = "V"; 337 | suffix = std::to_string(d.num); 338 | } else if (t == STATUS) { 339 | suffix = "F"; 340 | prefix = {d.flag}; 341 | } else if (t == PC) { 342 | prefix = "PC"; 343 | } else if (t == SP) { 344 | prefix = "SP"; 345 | } else { 346 | llvm_unreachable("name()"); 347 | } 348 | 349 | prefix.append(suffix); 350 | return prefix; 351 | } 352 | 353 | size_t StateReg::size() const { 354 | auto t = this->type; 355 | if (t == V) { 356 | return 128; 357 | } else if (t == STATUS) { 358 | return 1; 359 | } else if (t == PC || t == SP || t == X) { 360 | return 64; 361 | } else { 362 | llvm_unreachable("size()"); 363 | } 364 | } 365 | 366 | Type* StateReg::ty() const { 367 | return Type::getIntNTy(Context, this->size()); 368 | } 369 | -------------------------------------------------------------------------------- /src/state.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "llvm/IR/Module.h" 7 | #include "llvm/IR/Instructions.h" 8 | 9 | using namespace llvm; 10 | 11 | /** 12 | * Unified state representation: 13 | * x0..x31 : bits(64) (alias w) 14 | * v0..v31 : bits(128) (alias q d s h b) 15 | * nf, zf, cf, vf : bits(1) 16 | * pc 17 | */ 18 | 19 | extern const std::string entry_function_name; 20 | 21 | Function* findFunction(Module& m, std::string const& name); 22 | AllocaInst* findLocalVariable(Function& f, std::string const& name); 23 | std::vector generateGlobalState(Module& m, Function& f); 24 | void correctGlobalAccesses(const std::vector& globals); 25 | void correctMemoryAccesses(Module& m, Function& root); 26 | void noundef(LoadInst*); 27 | 28 | BasicBlock& newEntryBlock(Function& f); 29 | std::vector internaliseGlobals(Module& module, Function& f); 30 | std::vector internaliseParams(Function& f); 31 | ReturnInst& uniqueReturn(Function&); 32 | std::vector> functionReturns(Function&); 33 | 34 | enum StateType { 35 | X, // data is register num, as unsigned 36 | V, // data is register num, as unsigned 37 | STATUS, // data is uppercase ascii character, as char 38 | PC, // data unused 39 | SP 40 | }; 41 | 42 | struct StateReg { 43 | StateType type; 44 | union { 45 | int num; 46 | char flag; 47 | } data; 48 | 49 | std::string name() const; 50 | size_t size() const; 51 | Type* ty() const; 52 | }; 53 | 54 | 55 | template 56 | std::vector> clone_it(T&& range) { 57 | 58 | using namespace std::ranges; 59 | using V = range_value_t; 60 | using I = iterator_t; 61 | 62 | I itbegin = begin(range); 63 | I itend = end(range); 64 | 65 | std::vector vec{}; 66 | for (I i = itbegin; i != itend; i++) { 67 | vec.push_back(*i); 68 | } 69 | return vec; 70 | } 71 | -------------------------------------------------------------------------------- /src/translate.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "llvm/IR/Module.h" 4 | using namespace llvm; 5 | 6 | void capstone(Module& m); 7 | void remill(Module& m); 8 | void asl(Module& m); 9 | -------------------------------------------------------------------------------- /tools/bulk.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | set -e 5 | out="$1" 6 | if [[ -z "$out" ]]; then 7 | echo "specify output directory as first argument" 8 | exit 1; 9 | fi 10 | pwd="$(pwd)" 11 | mkdir -p "$out" 12 | cd $(dirname $0) 13 | 14 | . ./env.sh 15 | 16 | export OCAMLRUNPARAM=b 17 | set +e 18 | 19 | files="$(find "$ASLI_DIR/tests/coverage" -maxdepth 1 -name 'aarch64_*')" 20 | for f in $files; do 21 | echo $f 22 | mkdir -p "$pwd/$out/$(basename $f)" 23 | d=/tmp/$(date -I) 24 | mkdir -p $d 25 | 26 | ops=$(grep -R ' --> OK' "$f" --no-filename | cut -d: -f1) 27 | echo "$ops" | sed -E "s#0x(..)(..)(..)(..)#:dump A64 0x\1\2\3\4 $d/\4\3\2\1.aslb#" | "$ASLI" 28 | 29 | #echo "$ops" | sed 's/0x\(..\)\(..\)\(..\)\(..\)/\4\3\2\1/' | xargs -n 1 ./get_mnemonic.sh 30 | echo "$ops" | cat | sed 's/0x\(..\)\(..\)\(..\)\(..\)/\4\3\2\1/' | xargs -P 5 -i ./glue.sh '{}' "$pwd/$out/$(basename $f)" ';' 31 | done 32 | -------------------------------------------------------------------------------- /tools/env.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | search() { 4 | name=$1 5 | shift 6 | for f in "$@"; do 7 | if [[ -x $f ]] && [[ ! -d $f ]]; then 8 | echo "$f" 9 | return 0 10 | elif command -v "$f" >/dev/null; then 11 | echo "$(command -v $f)" 12 | return 0 13 | fi 14 | done 15 | echo "warning: cannot find '$name'. tried: $@" >&2 16 | exit 1 17 | } 18 | 19 | search-d() { 20 | name=$1 21 | subdir=$2 22 | shift 2 23 | for f in "$@"; do 24 | if [[ -d "$f" ]] && [[ -e "$f/$subdir" ]]; then 25 | echo "$f" 26 | return 0 27 | fi 28 | done 29 | echo "warning: cannot find dir for '$name' with contents '$subdir'. tried: $@" >&2 30 | exit 1 31 | } 32 | 33 | DIR="$(dirname "${BASH_SOURCE[0]}")"/.. 34 | DIR="$(realpath "$DIR")" 35 | export ASLI=$(search asli "$ASLI" $DIR/../asl-interpreter/asli aslp) 36 | export ASL_TRANSLATOR=$(search asl-translator "$ASL_TRANSLATOR" $DIR/asl-translator/_build/default/bin/main.exe asl-translator) 37 | export LLVM_TRANSLATOR=$(search llvm-translator "$LLVM_TRANSLATOR" $DIR/build/llvm-translator llvm-translator) 38 | export CAPSTONE=$(search retdec-capstone2llvmir "$CAPSTONE" $DIR/../retdec/build/prefix/bin/retdec-capstone2llvmir retdec-capstone2llvmir) 39 | export ALIVE=$(search alive-tv "$ALIVE" $DIR/../alive2/build/alive-tv alive-tv) 40 | export ASLI_DIR=$(search-d asli tests/coverage "$ASLI_DIR" "$(dirname $ASLI)" ~/.nix-profile/share/asli) 41 | 42 | for v in "$ASLI" "$ASL_TRANSLATOR" "$LLVM_TRANSLATOR" "$CAPSTONE" "$ALIVE" "$ASLI_DIR"; do 43 | if [[ -z "$v" ]]; then 44 | exit 1 45 | fi 46 | done 47 | -------------------------------------------------------------------------------- /tools/get_mnemonic.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [[ -z "$1" ]] && { echo "opcode required"; exit 1; } 4 | 5 | if [[ "$1" == 0x* ]]; then 6 | # 0x opcodes from ASLI are in big-endian format 7 | a=${1:6:2} 8 | b=${1:4:2} 9 | c=${1:2:2} 10 | d=${1:0:2} 11 | op="0x$a 0x$b 0x$c 0x$d" 12 | else 13 | # otherwise assume we have space separated bytes 14 | op=$(echo "$@" | tr -d ' ') 15 | d=${op:6:2} 16 | c=${op:4:2} 17 | b=${op:2:2} 18 | a=${op:0:2} 19 | op="0x$a 0x$b 0x$c 0x$d" 20 | fi 21 | 22 | echo "$op" | llvm-mc --arch arm64 -mattr=+crc,+flagm,+neon,+sve,+sve2,+dotprod,+fp-armv8,+sme,+v8.6a --disassemble | grep -v '.text' 23 | -------------------------------------------------------------------------------- /tools/glue.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | # glue.sh [opcode] [output directory] 5 | # opcode in little endian compressed format. 6 | # output directory is optional, 7 | # if given, log output is written to [opcode].{err,out} 8 | # in that directory 9 | # 10 | # LLVM and ASL files are written to a subfolder of 11 | # /tmp with the date. the subfolder path is logged. 12 | 13 | d="$2" 14 | if ! [[ -z "$d" ]]; then 15 | echo "$d/$1.out" "$d/$1.err" >&2 16 | exec 2>"$d/$1.err" 17 | exec 1>"$d/$1.out" 18 | fi 19 | 20 | cd $(dirname "$0")/.. 21 | 22 | . ./tools/env.sh 23 | 24 | 25 | function mnemonic() { 26 | op="$1" 27 | ./tools/get_mnemonic.sh $op 28 | } 29 | 30 | function asli() { 31 | op="$1" 32 | f=$2 33 | 34 | a=${op:0:2} 35 | b=${op:2:2} 36 | c=${op:4:2} 37 | d=${op:6:2} 38 | hex="0x${d}${c}${b}${a}" 39 | 40 | echo :dump A64 $hex "$f" | "$ASLI" 41 | x=$? 42 | 43 | return $x 44 | } 45 | 46 | function asl_translate() { 47 | in=$1 48 | out=$2 49 | "$ASL_TRANSLATOR" $in > $out 50 | x=$? 51 | return $x 52 | } 53 | 54 | function capstone() { 55 | op=$1 56 | f=$2 57 | "$CAPSTONE" -a arm64 -b 0x0 -c "$op" -o $f 58 | return $? 59 | } 60 | 61 | function remill() { 62 | op=$1 63 | f=$2 64 | docker run remill --arch aarch64 --ir_out /dev/stdout --bytes "$op" > $f 65 | return $? 66 | } 67 | 68 | function llvm_translate() { 69 | in=$1 70 | out=$2 71 | mode=$3 72 | 73 | "$LLVM_TRANSLATOR" $mode $in 2>&1 1>${out}tmp 74 | x=$? 75 | cat ${out}tmp | tools/post.sh > $out 76 | rm -f ${out}tmp 77 | 78 | return $x 79 | } 80 | 81 | function llvm_translate_vars() { 82 | "$LLVM_TRANSLATOR" vars $@ 83 | x=$? 84 | return $x 85 | } 86 | 87 | function alive() { 88 | a=${op:0:2} 89 | b=${op:2:2} 90 | c=${op:4:2} 91 | d=${op:6:2} 92 | hex="0x${d}${c}${b}${a}" 93 | 94 | echo '|' $hex 95 | echo '|' $1 96 | echo '|' $2 97 | 98 | "$ALIVE" --time-verify --smt-stats --bidirectional --disable-undef-input --disable-poison-input --smt-to=20000 $1 $2 99 | } 100 | 101 | function prefix() { 102 | sed "s/^/$1 --> /" 103 | } 104 | 105 | function main() { 106 | op=$1 107 | 108 | d=/tmp/$(date -I) 109 | mkdir -p $d 110 | 111 | aslb=$d/$op.aslb 112 | asl=$d/$op.asl 113 | cap=$d/$op.cap 114 | rem=$d/$op.rem 115 | 116 | aslll=$d/$op.asl.ll 117 | capll=$d/$op.cap.ll 118 | remll=$d/$op.rem.ll 119 | 120 | alive=$d/$op.alive.out 121 | 122 | mnemonic $op | prefix $op 123 | 124 | # asli $op $aslb 125 | test -f $aslb || { echo "executing ASLI"; asli $op $aslb; } 126 | test -f $aslb || { echo "$op ==> asli fail"; exit 1; } 127 | 128 | capstone $op $cap || { echo "$op ==> capstone fail"; exit 2; } 129 | remill $op $rem || { echo "$op ==> remill fail"; exit 3; } 130 | 131 | set -o pipefail 132 | asl_translate $aslb $asl | prefix $op || { echo "$op ==> asl-translator fail"; exit 4; } 133 | llvm_translate $cap $capll cap | prefix $op || { echo "$op ==> llvm-translator cap fail"; } 134 | llvm_translate $rem $remll rem | prefix $op || { echo "$op ==> llvm-translator rem fail"; } 135 | llvm_translate $asl $aslll asl | prefix $op || { echo "$op ==> llvm-translator asl fail"; exit 7; } 136 | llvm_translate_vars $aslll $capll $remll || { echo "$op ==> llvm-translator vars fail"; exit 8; } 137 | 138 | rm -f ${alive}{.rem,.cap,} 139 | mnemonic $op >> $alive.cap 140 | mnemonic $op >> $alive.rem 141 | alive $capll $aslll >> $alive.cap 142 | alive $remll $aslll >> $alive.rem 143 | 144 | cat $alive.cap >> $alive 145 | echo ========================================== >> $alive 146 | cat $alive.rem >> $alive 147 | 148 | grep --color=auto -E \ 149 | "seems to be correct|equivalent|reverse|doesn't verify|ERROR:|UB triggered|^[|] |failed" $alive \ 150 | | prefix $op 151 | 152 | echo $capll 153 | echo $remll 154 | echo $aslll 155 | echo $alive 156 | cap=$(grep 'seem to be equivalent' $alive.cap | wc -l) 157 | rem=$(grep 'seem to be equivalent' $alive.rem | wc -l) 158 | if [[ $cap == 1 && $rem == 1 ]]; then 159 | echo "$op ==> SUCCESS. cap $cap, rem $rem" 160 | else 161 | echo "$op ==> FAILED. cap $cap, rem $rem" 162 | fi 163 | } 164 | 165 | x="$(main "$1")" 166 | echo "$x" 167 | exec echo "$x" | grep -q 'SUCCESS' 168 | -------------------------------------------------------------------------------- /tools/log_checker.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import csv 4 | import collections 5 | import itertools 6 | 7 | from dataclasses import dataclass 8 | from itertools import chain, islice, repeat 9 | from typing import Generic, Iterator, Literal, TypeVar, Callable 10 | 11 | def main(argv): 12 | assert len(argv) >= 2, "requires csv file as second argument" 13 | assert len(argv) >= 3, "requires smaller csv file as third argument" 14 | larger = set() 15 | with open(argv[1], newline='') as f: 16 | read = csv.DictReader(f) 17 | for r in read: 18 | larger.add(r['mnemonic']) 19 | smaller = set() 20 | with open(argv[2], newline='') as f: 21 | read = csv.DictReader(f) 22 | for r in read: 23 | smaller.add(r['mnemonic']) 24 | print('\n'.join(sorted(larger - smaller))) 25 | 26 | if __name__ == '__main__': 27 | import sys 28 | main(sys.argv) 29 | -------------------------------------------------------------------------------- /tools/log_parser.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # parses the stdout output of ./bulk.sh into a csv file for data analysis 4 | 5 | 6 | 7 | import csv 8 | import collections 9 | import itertools 10 | 11 | from dataclasses import dataclass 12 | from itertools import chain, islice, repeat 13 | from typing import Generic, Iterator, Literal, TypeVar, Callable 14 | 15 | T = TypeVar('T') 16 | 17 | class PeekIterator(Generic[T]): 18 | EMPTY = object() 19 | 20 | def __init__(self, it): 21 | self.it = it 22 | self.prev = self.EMPTY 23 | self.repeat = False 24 | 25 | def __iter__(self): 26 | return self 27 | 28 | def __next__(self): 29 | if self.repeat: 30 | assert self.prev is not self.EMPTY 31 | self.repeat = False 32 | return self.prev 33 | 34 | self.prev = next(self.it) 35 | return self.prev 36 | 37 | def back(self): 38 | self.repeat = True 39 | 40 | 41 | def forever() -> Iterator[None]: 42 | return repeat(None) 43 | 44 | def takewhile(p, f): 45 | yield from itertools.takewhile(p, f) 46 | f.back() 47 | 48 | def takeuntil(p: Callable[[T], bool], f: PeekIterator[T]) -> PeekIterator[T]: 49 | """Takes from the given iterator up to and including the first value that satisfies p.""" 50 | yield from takewhile(lambda x: not p(x), f) 51 | yield next(f) 52 | 53 | 54 | def consume(iterator, n=None) -> None: 55 | "Advance the iterator n-steps ahead. If n is None, consume entirely." 56 | # Use functions that consume iterators at C speed. 57 | if n is None: 58 | # feed the entire iterator into a zero-length deque 59 | collections.deque(iterator, maxlen=0) 60 | else: 61 | # advance to the empty slice starting at position n 62 | next(islice(iterator, n, n), None) 63 | 64 | LifterResult = Literal['success', 'mismatch', 'ub', 'hypercall', 'timeout', 'domain', 'empty', 'unknown', 'variable'] 65 | 66 | @dataclass 67 | class Result: 68 | opcode: str # little-endian 69 | mnemonic: str 70 | category: str 71 | asl: Literal['success', 'fail'] 72 | cap_bool: bool = False 73 | rem_bool: bool = False 74 | cap: LifterResult = 'unknown' 75 | rem: LifterResult = 'unknown' 76 | detail: str = '' 77 | errors: str = '' 78 | 79 | def get_result(block: str) -> tuple[bool, LifterResult]: 80 | if 'These functions seem to be equivalent!' in block: 81 | return True, 'success' 82 | if 'Timeout' in block: 83 | return False, 'timeout' 84 | if 'UB triggered' in block: 85 | return False, 'ub' 86 | if 'Mismatch' in block: 87 | return False, 'mismatch' 88 | if 'return domain' in block: 89 | return False, 'domain' 90 | if block.count('\n') == 4 or '0 failed-to-prove' in block: 91 | return False, 'empty' 92 | if 'ERROR: ' in block: 93 | return False, 'unknown' 94 | print(repr(block)) 95 | assert False, 'unhandled result block' 96 | 97 | CAP_EMPTY = r''' 98 | entry: ; preds = %forced_vars 99 | %PC = load i64, ptr @PC, align 8, !noundef !0 100 | %0 = add i64 %PC, 4 101 | store i64 %0, ptr @PC, align 8 102 | ret void 103 | '''.strip() 104 | 105 | def parse_op(f: PeekIterator[str], op: str) -> Result: 106 | x = next(f) 107 | if '\t' not in x: 108 | mnemonic = 'unknown' 109 | f.back() 110 | else: 111 | op_old = op 112 | op, name, args = x.split('\t') 113 | op = op.split()[0] 114 | assert op == op_old 115 | mnemonic = (name + ' ' + args).strip() 116 | 117 | consume(takeuntil(lambda x: 'Capstone' in x, f)) 118 | 119 | l = list(takeuntil(lambda x: '==> FAILED' in x or '==> SUCCESS' in x, f)) 120 | detail = ''.join(l) 121 | l = PeekIterator(iter(l)) 122 | if 'asl-translator fail' in detail: 123 | return Result(op, mnemonic, '', False, detail=detail) 124 | if 'llvm-translator vars fail' in detail: 125 | return Result(op, mnemonic, '', False, detail=detail) 126 | 127 | head = ''.join(takewhile(lambda x: ' --> | ' not in x, l)) 128 | hypercall = 'hyper_call' in head 129 | 130 | lifter_block = lambda: chain( 131 | takewhile(lambda x: ' --> | ' in x, l), 132 | takewhile(lambda x: ' --> | ' not in x and ' ==> ' not in x, l) 133 | ) 134 | 135 | cap_block = ''.join(lifter_block()) 136 | cap_bool,cap = get_result(cap_block) 137 | if 'unhandled capstone variable' in detail: 138 | cap = 'variable' 139 | else: 140 | cap_ll = [l for l in cap_block.splitlines() if l.endswith('.cap.ll')][0] 141 | cap_ll = cap_ll.split('--> | ')[-1] 142 | with open(cap_ll) as f: 143 | if CAP_EMPTY in f.read(): 144 | cap = 'empty' 145 | 146 | rem_block = ''.join(lifter_block()) 147 | rem_bool,rem = get_result(rem_block) 148 | if hypercall: rem = 'hypercall' 149 | 150 | return Result(op, mnemonic, '', True, (cap_bool), (rem_bool), cap, rem, detail) 151 | 152 | 153 | def main(argv): 154 | assert len(argv) >= 2, "log directory required as first argument" 155 | assert len(argv) >= 3, "out file required as second argument" 156 | 157 | from pathlib import Path 158 | 159 | fname = argv[1] 160 | results = [] 161 | for d in Path(fname).iterdir(): 162 | if not d.is_dir(): continue 163 | for f in d.iterdir(): 164 | print(f) 165 | if not f.name.endswith('.out'): continue 166 | with open(f) as file: 167 | x = parse_op(PeekIterator(iter(file)), f.stem) 168 | x.category = d.name 169 | x.errors = f.with_suffix('.err').read_text() 170 | 171 | results.append(x) 172 | 173 | print(len(results)) 174 | 175 | with open(argv[2], 'w', newline='') as f: 176 | fields = list(results[0].__dict__.keys()) 177 | w = csv.DictWriter(f, fields) 178 | w.writeheader() 179 | w.writerows((x.__dict__ for x in results)) 180 | 181 | if __name__ == '__main__': 182 | import sys 183 | main(sys.argv) 184 | -------------------------------------------------------------------------------- /tools/main.ll: -------------------------------------------------------------------------------- 1 | @i64format = private constant [8 x i8] c"-> %ld\0A\00" 2 | 3 | declare i32 @printf(ptr, ...) 4 | 5 | define i32 @main() { 6 | store i64 2917964791673343281, ptr @X2 7 | store i64 6305407245181432527, ptr @X3 8 | 9 | call void @root() 10 | 11 | %x1 = load i64, ptr @X1 12 | %pc = load i64, ptr @PC 13 | 14 | %n = load i1, ptr @NF 15 | %z = load i1, ptr @ZF 16 | %c = load i1, ptr @CF 17 | %v = load i1, ptr @VF 18 | 19 | %n64 = zext i1 %n to i64 20 | %z64 = zext i1 %z to i64 21 | %c64 = zext i1 %c to i64 22 | %v64 = zext i1 %v to i64 23 | 24 | 25 | call i32 @printf(ptr @i64format, i64 %x1) 26 | call i32 @printf(ptr @i64format, i64 %n64) 27 | call i32 @printf(ptr @i64format, i64 %z64) 28 | call i32 @printf(ptr @i64format, i64 %c64) 29 | call i32 @printf(ptr @i64format, i64 %v64) 30 | call i32 @printf(ptr @i64format, i64 %pc) 31 | 32 | ret i32 121 33 | } 34 | -------------------------------------------------------------------------------- /tools/post.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | opt -S -opaque-pointers -passes=inline,mergereturn,mem2reg,gvn,early-cse,simplifycfg,tailcallelim,simplifycfg,instcombine,gvn,dce 5 | #opt -S -opaque-pointers -passes=inline,mergereturn,simplifycfg,mem2reg,dce,dse,sink,sccp,gvn,dse,dce,verify 6 | #opt -S -opaque-pointers -passes=inline,mergereturn,gvn,mem2reg,dce,dse,sink,dse,mem2reg,dce,verify 7 | --------------------------------------------------------------------------------