├── .github └── workflows │ └── main.yml ├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md ├── api ├── branch_decoder_support.c ├── generate_emit_wrapper.rb ├── hash_table.c ├── hash_table.h ├── helpers.c ├── helpers.h ├── internal.c ├── load_store.c ├── plugin_support.c └── plugin_support.h ├── arch ├── aarch32 │ ├── dispatcher_aarch32.S │ ├── dispatcher_aarch32.c │ ├── scanner_a32.c │ └── scanner_t32.c ├── aarch64 │ ├── dispatcher_aarch64.S │ ├── dispatcher_aarch64.c │ └── scanner_a64.c └── riscv │ ├── dispatcher_riscv.S │ ├── dispatcher_riscv.c │ ├── riscv_traces.c │ ├── riscv_traces.h │ └── scanner_riscv.c ├── common.c ├── common.h ├── dbm.c ├── dbm.h ├── dispatcher.c ├── docker ├── Dockerfile └── README.md ├── docs ├── talks │ └── riscv2024 │ │ └── presentation.pdf └── tutorials │ ├── hipeac2024 │ ├── README.md │ ├── appendix │ │ └── README.md │ ├── exercise1 │ │ ├── README.md │ │ ├── code │ │ │ └── tutorial.c │ │ └── solution │ │ │ └── solution.c │ ├── exercise2 │ │ ├── README.md │ │ ├── code │ │ │ └── tutorial.c │ │ └── solution │ │ │ └── solution.c │ ├── exercise3 │ │ ├── README.md │ │ ├── code │ │ │ └── tutorial.c │ │ └── solution │ │ │ └── solution.c │ ├── exercise4 │ │ ├── README.md │ │ ├── code │ │ │ └── tutorial.c │ │ └── solution │ │ │ └── solution.c │ ├── introduction │ │ ├── README.md │ │ ├── code │ │ │ ├── Makefile │ │ │ ├── test.c │ │ │ └── tutorial.c │ │ └── mambo │ │ │ └── makefile │ └── presentation.pdf │ ├── hipeac2025 │ ├── README.md │ ├── appendix │ │ └── README.md │ ├── exercise1 │ │ ├── README.md │ │ ├── code │ │ │ └── tutorial.c │ │ └── solution │ │ │ └── solution.c │ ├── exercise2 │ │ ├── README.md │ │ ├── code │ │ │ └── tutorial.c │ │ └── solution │ │ │ └── solution.c │ ├── exercise3 │ │ ├── README.md │ │ ├── code │ │ │ └── tutorial.c │ │ └── solution │ │ │ └── solution.c │ ├── exercise4 │ │ ├── README.md │ │ ├── code │ │ │ └── tutorial.c │ │ └── solution │ │ │ └── solution.c │ └── introduction │ │ ├── README.md │ │ ├── code │ │ ├── Makefile │ │ ├── test.c │ │ └── tutorial.c │ │ └── mambo │ │ └── makefile │ └── start-guide │ ├── README.md │ ├── exercise0 │ └── README.md │ ├── exercise1 │ └── README.md │ ├── exercise2 │ ├── README.md │ └── images │ │ ├── Context_Flow.png │ │ ├── ELF-File.png │ │ ├── ELF-Loader.png │ │ ├── Memory-Allocation.png │ │ ├── Scanner-Code.png │ │ ├── Syscall_Signal.png │ │ ├── basic-block.png │ │ ├── branch.png │ │ ├── cache-dipatcher.png │ │ ├── empty.png │ │ ├── plugins.png │ │ └── syscall.png │ └── simple_program.c ├── elf ├── elf_loader.c ├── elf_loader.h └── symbol_parser.c ├── kernel_sigaction.h ├── makefile ├── pie ├── .gitignore ├── LICENSE ├── a64.txt ├── arm.txt ├── generate_common.rb ├── generate_decoder.rb ├── generate_encoder.rb ├── generate_field-decoder.rb ├── makefile ├── riscv.txt └── thumb.txt ├── plugins.h ├── plugins ├── branch_count.c ├── cachesim │ ├── README.md │ ├── cachesim.S │ ├── cachesim.c │ ├── cachesim_buffer.h │ ├── cachesim_model.c │ └── cachesim_model.h ├── datarace │ ├── README.md │ ├── datarace.c │ ├── datarace.h │ └── detectors │ │ ├── detector.h │ │ ├── djit.c │ │ └── fasttrack.c ├── follow_exec.c ├── hotspot.c ├── instruction_mix.c ├── memcheck │ ├── README.md │ ├── memcheck.S │ ├── memcheck.c │ ├── memcheck.h │ └── naive_stdlib.c ├── mtrace.S ├── mtrace.c ├── mtrace.h ├── poc_log_returns.c ├── soft_div.c ├── strace.c ├── symbol_example.c └── tb_count.c ├── scanner_common.h ├── scanner_public.h ├── signals.c ├── syscalls.c ├── syscalls.h ├── test ├── .gitignore ├── arm_insts │ ├── v8.1 │ │ ├── CASPx.c │ │ ├── CASx.c │ │ ├── LDADDx.c │ │ ├── LDCLRx.c │ │ ├── LDEORx.c │ │ ├── LDLARx.c │ │ ├── LDSETx.c │ │ ├── LDSMAXx.c │ │ ├── LDSMINx.c │ │ ├── LDUMAXx.c │ │ ├── LDUMINx.c │ │ ├── SQRDMLxH.c │ │ ├── STADDx.c │ │ ├── STCLRx.c │ │ ├── STEORx.c │ │ ├── STLLRx.c │ │ ├── STSETx.c │ │ ├── STSMAXx.c │ │ ├── STSMINx.c │ │ ├── STUMAXx.c │ │ ├── STUMINx.c │ │ ├── SWPx.c │ │ ├── VQRDMLAH.c │ │ └── makefile │ └── v8.2 │ │ ├── ATS1E1RP.c │ │ ├── ATS1E1WP.c │ │ ├── BFC.c │ │ ├── CRYPTO.c │ │ ├── DCCVAP.c │ │ ├── FEAT_FHM_64.c │ │ ├── FEAT_FP16_64.c │ │ ├── FMMLA.c │ │ ├── LD1ROx.c │ │ ├── REV64.c │ │ ├── TRNx.c │ │ ├── UZPx.c │ │ ├── ZIPx.c │ │ ├── makefile │ │ └── xDOT.c ├── hw_div.S ├── ihl_test.c ├── load_store.S ├── load_store.c ├── makefile ├── mmap_munmap.c ├── mprotect_exec.c ├── self_modifying.c ├── signals.S └── signals.c ├── traces.c ├── traces_common.c ├── traces_common.h ├── util.S └── util.h /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: build-and-run-mambo 2 | run-name: Building and running MAMBO triggered by ${{ github.actor }} on ${{ github.ref }} 3 | on: 4 | push: 5 | branches: [master] 6 | pull_request: 7 | types: [opened, synchronize, reopened] 8 | jobs: 9 | build-and-run-mambo: 10 | strategy: 11 | matrix: 12 | os: [focal] 13 | arch: [ {os: arm64, qemu: aarch64}, {os: riscv64, qemu: riscv64}, {os: armhf, qemu: arm} ] 14 | fail-fast: false 15 | runs-on: ubuntu-22.04 16 | steps: 17 | - uses: actions/checkout@v4 18 | with: 19 | path: mambo 20 | submodules: true 21 | - name: Set up host environment 22 | run: | 23 | sudo apt-get update 24 | sudo apt-get upgrade 25 | sudo apt-get install -y debootstrap 26 | sudo apt-get install -y qemu-user-static 27 | sudo mkdir -p /tmp/chroot/ 28 | sudo chown root /bin/tar 29 | sudo chmod u+s /bin/tar 30 | - uses: actions/cache/restore@v4 31 | id: cache 32 | with: 33 | path: /tmp/chroot/${{ matrix.arch.os }} 34 | key: ${{ matrix.os }}.${{ matrix.arch.os }} 35 | - name: Install and configure sysroot 36 | if: steps.cache.outputs.cache-hit != 'true' 37 | run: | 38 | sudo debootstrap --arch=${{ matrix.arch.os }} --foreign ${{ matrix.os }} /tmp/chroot/${{ matrix.arch.os }} http://ports.ubuntu.com/ubuntu-ports 39 | sudo cp /usr/bin/qemu-${{ matrix.arch.qemu }}-static /tmp/chroot/${{ matrix.arch.os }}/usr/bin/ 40 | sudo chroot /tmp/chroot/${{ matrix.arch.os }}/ /usr/bin/qemu-${{ matrix.arch.qemu }}-static /bin/bash -c '/debootstrap/debootstrap --second-stage' 41 | - uses: actions/cache/save@v4 42 | if: steps.cache.outputs.cache-hit != 'true' 43 | with: 44 | path: /tmp/chroot/${{ matrix.arch.os }} 45 | key: ${{ matrix.os }}.${{ matrix.arch.os }} 46 | - name: Build and run MAMBO inside chroot 47 | run: | 48 | sudo cp -r $GITHUB_WORKSPACE/mambo /tmp/chroot/${{ matrix.arch.os }}/root 49 | sudo chroot /tmp/chroot/${{ matrix.arch.os }}/ /usr/bin/qemu-${{ matrix.arch.qemu }}-static /bin/bash -c 'sudo apt-get update; sudo apt-get upgrade -y; sudo apt-get -y install build-essential libelf-dev ruby; cd /root/mambo/; make' 50 | sudo chroot /tmp/chroot/${{ matrix.arch.os }}/ /usr/bin/qemu-${{ matrix.arch.qemu }}-static /bin/bash -c '/root/mambo/dbm /bin/ls' 51 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dbm 2 | api/emit_*.c 3 | api/emit_*.h 4 | elf/elf_loader.o 5 | elf/symbol_parser.o 6 | .vscode/ 7 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beehive-lab/mambo/dcdf19a751092c18cccc1e31fea684dfc599c8b8/.gitmodules -------------------------------------------------------------------------------- /api/generate_emit_wrapper.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | 3 | This file is part of MAMBO, a low-overhead dynamic binary modification tool: 4 | https://github.com/beehive-lab/mambo 5 | 6 | Copyright 2013-2016 Cosmin Gorgovan 7 | 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | 20 | =end 21 | 22 | # Quick and dirty generator for emit-style function encoding wrappers for plugins 23 | # Takes as argument the path to the C file of an instruction encoder generated by PIE 24 | 25 | def get_filecode() 26 | "__EMIT_#{ARGV[0].gsub(/[^\w]/, "_").upcase}__" 27 | end 28 | 29 | def generate_header() 30 | puts "#ifdef PLUGINS_NEW" 31 | if (@header_only) 32 | puts "#ifndef #{get_filecode()}" 33 | puts "#define #{get_filecode()}" 34 | end 35 | puts "#include \"../dbm.h\"\n" 36 | puts "#include \"../#{ARGV[0].gsub(".c", ".h")}\"" 37 | puts "#include \"plugin_support.h\"\n" 38 | end 39 | 40 | def generate_footer() 41 | if (@header_only) 42 | puts "#endif" 43 | end 44 | puts "#endif" 45 | end 46 | 47 | def rewrite_name(name) 48 | name.gsub('void ', 'void emit_') 49 | end 50 | 51 | def generate_body(name, fields, size) 52 | puts ")\n{" 53 | print "\t#{name}((uint#{@min_size * 8}_t **)(&ctx->code.write_p)" 54 | 55 | fields.each do |field| 56 | print ", #{field}" 57 | end 58 | 59 | puts ");" 60 | puts "\tctx->code.write_p += #{size};\n}" 61 | end 62 | 63 | def process_file(filename) 64 | fields = [] 65 | name = "" 66 | size = 0 67 | File.readlines(filename).each do |line| 68 | if (line.match(/^void/)) 69 | puts rewrite_name(line) 70 | line = line.split(' ') 71 | name = line[1] 72 | fields = [] 73 | elsif (line.match(/address,?$/)) 74 | print "\tmambo_context *ctx" 75 | #get the base instruction size, should be either uint16_t or uint32_t 76 | size = line.match(/[0-9]+/)[0].to_i / 8 77 | @min_size = size if (size < @min_size) 78 | elsif (line.match(/^\tunsigned int/)) 79 | # function arguments, stripped of commas and excluding the address 80 | line = line.match(/[\w\s]+/)[0] 81 | print ",\n#{line}" 82 | line = line.split(' ') 83 | fields.push(line[line.size-1]) 84 | elsif (line.include?("**address = ") or line.include?("*(*address) =")) 85 | puts if (fields.size == 0) 86 | if (@header_only) 87 | puts ");" 88 | else 89 | size *= 2 if (line.include?("*(*address")) 90 | generate_body(name, fields, size) 91 | end 92 | end 93 | end 94 | end 95 | 96 | abort "Syntax: generate_emit_wrapper.rb [header]" unless (ARGV[0]) 97 | @header_only = true if (ARGV[1] and ARGV[1] == "header") 98 | @min_size = 4; 99 | 100 | generate_header() 101 | process_file(ARGV[0]) 102 | generate_footer() 103 | 104 | -------------------------------------------------------------------------------- /api/hash_table.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of MAMBO, a low-overhead dynamic binary modification tool: 3 | https://github.com/beehive-lab/mambo 4 | 5 | Copyright 2017-2020 The University of Manchester 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | #ifndef __MAMBO_HASH_TABLE_H__ 21 | #define __MAMBO_HASH_TABLE_H__ 22 | 23 | #include 24 | 25 | typedef struct { 26 | uintptr_t key; 27 | uintptr_t value; 28 | } mambo_ht_entry_t; 29 | 30 | typedef struct { 31 | size_t size; 32 | size_t entry_count; 33 | 34 | int index_shift; 35 | 36 | bool allow_resize; 37 | int fill_factor; 38 | size_t resize_threshold; 39 | 40 | pthread_mutex_t lock; 41 | 42 | mambo_ht_entry_t *entries; 43 | } mambo_ht_t; 44 | 45 | /** 46 | * @brief Initialises a hash-table with specific configuration. 47 | * 48 | * Initialises a hash-table 49 | * 50 | * @pre @c ctx->thread_data must not be @c NULL. 51 | * 52 | * @param ctx The context that holds the plugin state. 53 | * @return The id of the calling thread. 54 | */ 55 | int mambo_ht_init(mambo_ht_t *ht, size_t initial_size, int index_shift, int fill_factor, bool allow_resize); 56 | int mambo_ht_add_nolock(mambo_ht_t *ht, uintptr_t key, uintptr_t value); 57 | int mambo_ht_add(mambo_ht_t *ht, uintptr_t key, uintptr_t value); 58 | int mambo_ht_get_nolock(mambo_ht_t *ht, uintptr_t key, uintptr_t *value); 59 | int mambo_ht_get(mambo_ht_t *ht, uintptr_t key, uintptr_t *value); 60 | 61 | #endif -------------------------------------------------------------------------------- /arch/riscv/riscv_traces.h: -------------------------------------------------------------------------------- 1 | #ifndef __RISCV_TRACES_H__ 2 | #define __RISCV_TRACES_H__ 3 | 4 | void create_trace(dbm_thread *thread_data, uint16_t bb_source, uintptr_t *ret_addr); 5 | void trace_dispatcher(uintptr_t target, uintptr_t *next_addr, uint32_t source_index, dbm_thread *thread_data); 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /common.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of MAMBO, a low-overhead dynamic binary modification tool: 3 | https://github.com/beehive-lab/mambo 4 | 5 | Copyright 2013-2016 Cosmin Gorgovan 6 | Copyright 2017-2020 The University of Manchester 7 | 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | */ 20 | 21 | #ifndef __COMMON_H__ 22 | #define __COMMON_H__ 23 | 24 | #include 25 | 26 | #define CODE_CACHE_HASH_SIZE 0x7FFFF//14071 27 | #define CODE_CACHE_HASH_OVERP 10 28 | 29 | /* Warning, size MUST be (a power of 2) */ 30 | #if __arm__ 31 | #define HT_SHIFT 0 32 | #elif __aarch64__ 33 | #define HT_SHIFT 2 34 | #elif __riscv_compressed 35 | #define HT_SHIFT 1 36 | #elif __riscv 37 | #define HT_SHIFT 2 38 | #endif 39 | #define GET_INDEX(key) ((key >> HT_SHIFT) & (table->size - CODE_CACHE_HASH_OVERP)) 40 | typedef struct { 41 | uintptr_t key; 42 | uintptr_t value; 43 | } hash_entry; 44 | 45 | typedef struct { 46 | int size; 47 | int collisions; 48 | int count; 49 | hash_entry entries[CODE_CACHE_HASH_SIZE + CODE_CACHE_HASH_OVERP]; 50 | } hash_table; 51 | 52 | struct ll_entry_s { 53 | struct ll_entry_s *next; 54 | uintptr_t data; 55 | }; 56 | typedef struct ll_entry_s ll_entry; 57 | 58 | typedef struct { 59 | ll_entry *free_list; 60 | int size; 61 | ll_entry pool[]; 62 | } ll; 63 | 64 | typedef struct { 65 | uintptr_t start; 66 | uintptr_t end; 67 | int fd; 68 | } interval_map_entry; 69 | 70 | typedef struct { 71 | ssize_t mem_size; 72 | ssize_t entry_count; 73 | pthread_mutex_t mutex; 74 | interval_map_entry *entries; 75 | } interval_map; 76 | 77 | bool hash_add(hash_table *table, uintptr_t key, uintptr_t value); 78 | void hash_delete(hash_table *table, uintptr_t key); 79 | uintptr_t hash_lookup(hash_table *table, uintptr_t key); 80 | void hash_init(hash_table *table, int size); 81 | 82 | void linked_list_init(ll *list, int size); 83 | ll_entry *linked_list_alloc(ll *list); 84 | 85 | int interval_map_init(interval_map *imap, ssize_t size); 86 | int interval_map_add(interval_map *imap, uintptr_t start, size_t len, int fd); 87 | ssize_t interval_map_search(interval_map *imap, uintptr_t start, size_t len); 88 | int interval_map_search_by_addr(interval_map *imap, uintptr_t addr, interval_map_entry *entry); 89 | ssize_t interval_map_delete(interval_map *imap, uintptr_t start, size_t len); 90 | 91 | uint32_t next_reg_in_list(uint32_t reglist, uint32_t start); 92 | uint32_t last_reg_in_list(uint32_t reglist, uint32_t start); 93 | int get_lowest_n_regs(uint32_t reglist, uint32_t *regs, int n); 94 | int get_highest_n_regs(uint32_t reglist, uint32_t *regs, int n); 95 | int count_bits(uint32_t n); 96 | int try_memcpy(void *dst, void *src, size_t n); 97 | 98 | static inline uintptr_t align_lower(uintptr_t address, uintptr_t alignment) { 99 | uintptr_t aligned_address = address / alignment * alignment; 100 | 101 | return aligned_address; 102 | } 103 | 104 | static inline uintptr_t align_higher(uintptr_t address, uintptr_t alignment) { 105 | uintptr_t aligned_address = align_lower(address, alignment); 106 | if (aligned_address != address) { 107 | aligned_address += alignment; 108 | } 109 | 110 | return aligned_address; 111 | } 112 | 113 | static inline bool is_offset_within_range(intptr_t const offset, intptr_t const range) { 114 | return ((offset <= (range - 4)) && (offset >= (- range))); 115 | } 116 | #endif 117 | -------------------------------------------------------------------------------- /dispatcher.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of MAMBO, a low-overhead dynamic binary modification tool: 3 | https://github.com/beehive-lab/mambo 4 | 5 | Copyright 2013-2016 Cosmin Gorgovan 6 | Copyright 2015-2017 Guillermo Callaghan 7 | Copyright 2017-2020 The University of Manchester 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | Unless required by applicable law or agreed to in writing, software 16 | distributed under the License is distributed on an "AS IS" BASIS, 17 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | See the License for the specific language governing permissions and 19 | limitations under the License. 20 | */ 21 | 22 | #include 23 | 24 | #include "dbm.h" 25 | #include "scanner_common.h" 26 | #ifdef __arm__ 27 | void dispatcher_aarch32(dbm_thread *thread_data, uint32_t source_index, 28 | branch_type exit_type, uintptr_t target, 29 | uintptr_t block_address); 30 | #elif __aarch64__ 31 | void dispatcher_aarch64(dbm_thread *thread_data, uint32_t source_index, 32 | branch_type exit_type, uintptr_t target, 33 | uintptr_t block_address); 34 | #endif 35 | #ifdef __riscv 36 | void dispatcher_riscv(dbm_thread *thread_data, uint32_t source_index, branch_type exit_type, 37 | uintptr_t target, uintptr_t block_address); 38 | #include "arch/riscv/riscv_traces.h" 39 | #endif 40 | 41 | #ifdef DEBUG 42 | #define debug(...) fprintf(stderr, __VA_ARGS__) 43 | #else 44 | #define debug(...) 45 | #endif 46 | 47 | void dispatcher(const uintptr_t target, const uint32_t source_index, 48 | uintptr_t * const next_addr, dbm_thread * const thread_data) { 49 | /* It's essential to copy exit_branch_type before calling lookup_or_scan 50 | because when scanning a stub basic block the source block and its 51 | meta-information get overwritten */ 52 | debug("Source block index: %d\n", source_index); 53 | branch_type source_branch_type = 54 | thread_data->code_cache_meta[source_index].exit_branch_type; 55 | 56 | #ifdef DBM_TRACES 57 | // Handle trace exits separately 58 | if (source_index >= CODE_CACHE_SIZE) { 59 | #ifdef __arm__ 60 | if (source_branch_type != tbb && source_branch_type != tbh) 61 | #endif 62 | return trace_dispatcher(target, next_addr, source_index, thread_data); 63 | } 64 | #endif 65 | 66 | debug("Reached the dispatcher, target: 0x%" PRIxPTR ", ret: %p, src: %d thr: %p\n", 67 | target, next_addr, source_index, thread_data); 68 | thread_data->was_flushed = false; 69 | 70 | #ifdef DEBUG 71 | bool cached; 72 | *next_addr = lookup_or_scan_with_cached(thread_data, target, &cached); 73 | if (cached) { 74 | debug("Found block from %d for 0x%" PRIxPTR " in cache at 0x%" PRIxPTR "\n", 75 | source_index, target, *next_addr); 76 | } else { 77 | debug("Scanned at 0x%" PRIxPTR " for 0x%" PRIxPTR "\n", *next_addr, target); 78 | } 79 | #else 80 | *next_addr = lookup_or_scan(thread_data, target); 81 | #endif 82 | 83 | // Bypass any linking 84 | if (source_index == 0 || thread_data->was_flushed) { 85 | return; 86 | } 87 | 88 | #ifdef __arm__ 89 | dispatcher_aarch32(thread_data, source_index, source_branch_type, target, 90 | *next_addr); 91 | #endif 92 | #ifdef __aarch64__ 93 | dispatcher_aarch64(thread_data, source_index, source_branch_type, target, 94 | *next_addr); 95 | #endif 96 | #ifdef __riscv 97 | dispatcher_riscv(thread_data, source_index, source_branch_type, target, 98 | *next_addr); 99 | #endif 100 | } 101 | -------------------------------------------------------------------------------- /docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:22.04 2 | 3 | RUN apt-get update 4 | RUN apt-get install -y qemu-system-misc opensbi u-boot-qemu 5 | RUN apt-get install -y qemu-system-aarch64 qemu-efi 6 | RUN apt-get install -y wget xz-utils git build-essential libelf-dev ruby gdb sudo 7 | 8 | #create new user 9 | RUN useradd -ms /bin/bash mambo 10 | RUN echo 'mambo:mambo' | chpasswd 11 | RUN usermod -a -G sudo mambo 12 | 13 | USER mambo 14 | WORKDIR /home/mambo 15 | 16 | #create directories for mambo riscv and mambo ARM 17 | RUN mkdir aarch64 18 | RUN mkdir riscv 19 | 20 | WORKDIR /home/mambo/aarch64 21 | RUN wget https://cdimage.ubuntu.com/ubuntu-server/noble/daily-preinstalled/current/noble-preinstalled-server-arm64.img.xz 22 | RUN unxz noble-preinstalled-server-arm64.img.xz 23 | RUN qemu-img resize noble-preinstalled-server-arm64.img +8G 24 | RUN cp /usr/share/AAVMF/AAVMF_CODE.fd flash1.img 25 | RUN chown mambo flash1.img 26 | RUN echo "#!/bin/bash\n\nqemu-system-aarch64 -machine virt -cpu cortex-a57 -smp 2 -m 4096 -nographic -bios flash1.img -netdev user,id=net0 -device virtio-net-device,netdev=net0 -drive file=noble-preinstalled-server-arm64.img,format=raw,if=virtio -device virtio-rng-pci -serial mon:stdio -device virtio-gpu-pci -full-screen -device qemu-xhci -device usb-kbd -device usb-mouse\n" > run-qemu-arm64.sh 27 | RUN chown mambo run-qemu-arm64.sh 28 | 29 | WORKDIR /home/mambo/riscv 30 | RUN wget https://cdimage.ubuntu.com/ubuntu-server/noble/daily-preinstalled/current/noble-preinstalled-server-riscv64.img.xz 31 | RUN unxz noble-preinstalled-server-riscv64.img.xz 32 | RUN qemu-img resize noble-preinstalled-server-riscv64.img +8G 33 | RUN echo "#!/bin/bash\n\nqemu-system-riscv64 -machine virt -m 4G -smp cpus=2 -nographic -bios /usr/lib/riscv64-linux-gnu/opensbi/generic/fw_jump.bin -kernel /usr/lib/u-boot/qemu-riscv64_smode/u-boot.bin -netdev user,id=net0 -device virtio-net-device,netdev=net0 -drive file=noble-preinstalled-server-riscv64.img,format=raw,if=virtio -device virtio-rng-pci\n" > run-qemu-riscv.sh 34 | RUN chown mambo run-qemu-riscv.sh 35 | 36 | 37 | USER mambo 38 | ENV ARM64='/home/mambo/aarch64' 39 | ENV RISCV='/home/mambo/riscv' 40 | WORKDIR /home/mambo 41 | RUN chmod u+x aarch64/run-qemu-arm64.sh 42 | RUN chmod u+w aarch64/flash1.img 43 | RUN chmod u+x riscv/run-qemu-riscv.sh 44 | -------------------------------------------------------------------------------- /docker/README.md: -------------------------------------------------------------------------------- 1 | # Getting MAMBO Set Up 2 | 3 | The following guide will walk you through getting MAMBO for ARM64 or RISC-V 64-bit set up. 4 | 5 | ## Requirements 6 | Docker is required. Please see the following instructions to install docker on your machine: https://docs.docker.com/get-docker/ 7 | 8 | ## Common Setup 9 | 1. Clone MAMBO repository or copy the [Dockerfile](https://github.com/beehive-lab/mambo/blob/master/docker/Dockerfile) into your local filesystem 10 | 2. Run the Dockerfile using the following command: `docker build --tag "mambo:latest" .` Note the `.` at the end is the current directory where the Dockerfile is 11 | 3. Run the docker image we just created using the following command: `docker run -t -i mambo` 12 | 4. You will now be in the home directory of the docker container. Two directories are available `aarch64` for those wishing to use MAMBO on ARM64, and `riscv` for those wishing to use MAMBO on RISC-V. Navigate to the desired directory and follow the instructions for each architecure in the relevant section below. 13 | 14 | ## MAMBO on ARM64 15 | 16 | ### Running on a non-ARM64 machine 17 | 18 | Here, a prebuilt server image for ubuntu will be run under QEMU. 19 | 20 | 1. Run `cd $ARM64` 21 | 2. Run QEMU with the script `run-qemu-arm64.sh` and login with the username `ubuntu` and password `ubuntu` 22 | 3. Install dependencies: `sudo apt-get update && sudo apt-get install build-essential libelf-dev ruby` 23 | 4. Clone MAMBO using the following command: `git clone https://github.com/beehive-lab/mambo.git` 24 | 5. Set an environment variable for mambo `export MAMBO_ROOT=/home/ubuntu/mambo` 25 | 6. Change to the cloned directory: `cd $MAMBO_ROOT` 26 | 7. Change line 33 of the makefile to: `LIBS=-lelf -lpthread -lz -lzstd` 27 | 8. Build MAMBO: `make` 28 | 29 | 30 | 31 | ### Running on an ARM-64 machine (eg. Apple Silicon) 32 | 33 | 1. Run `cd $ARM64` 34 | 2. Clone MAMBO using the following command: `git clone https://github.com/beehive-lab/mambo.git` 35 | 3. Set an environment variable for mambo `export MAMBO_ROOT=$ARM64/mambo` 36 | 3. Change to the cloned directory: `cd $MAMBO_ROOT` 37 | 4. Build MAMBO: `make` 38 | 39 | ## MAMBO on RISCV 40 | 41 | Here, a prebuilt server image for ubuntu will be run under QEMU. 42 | 43 | 1. Run `cd $RISCV` 44 | 2. Run QEMU with the script `run-qemu-riscv.sh` and login with the username `ubuntu` and password `ubuntu` 45 | 3. Install dependencies: `sudo apt-get update && sudo apt-get install build-essential libelf-dev ruby` 46 | 4. Clone MAMBO using the following command: `git clone https://github.com/beehive-lab/mambo.git` 47 | 5. Set an environment variable for mambo `export MAMBO_ROOT=/home/ubuntu/mambo` 48 | 6. Change to the cloned directory: `cd $MAMBO_ROOT` 49 | 7. Change line 33 of the makefile to: `LIBS=-lelf -lpthread -lz -lzstd` 50 | 8. Build MAMBO: `make` 51 | -------------------------------------------------------------------------------- /docs/talks/riscv2024/presentation.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beehive-lab/mambo/dcdf19a751092c18cccc1e31fea684dfc599c8b8/docs/talks/riscv2024/presentation.pdf -------------------------------------------------------------------------------- /docs/tutorials/hipeac2024/README.md: -------------------------------------------------------------------------------- 1 | # MAMBO - Dynamic Binary Instrumentation on ARM and RISC-V 💻 Welcome!! 2 | 3 | Access the slides [here](presentation.pdf). 4 | 5 | ## Getting Started 6 | 7 | - Install Docker 8 | 9 | Visit the [link](https://github.com/beehive-lab/mambo/tree/master/docker) to find details about MAMBO on Docker. 10 | 11 | - Directory structure 12 | 13 | Each exercise contains the following folders: 14 | - `code`: This folder contains the template of the MAMBO plugin for each exercise that you need to modify/add code in the `TODO` sections. 15 | 16 | - `solution`: This folder contains the implemented MAMBO plugin for each exercise. 17 | 18 | > [!NOTE] 19 | > MAMBO can be also run natively, without Docker, on Armv8 Linux machines. Speak to us if you wish to do so and have any problems. 20 | 21 | > [!NOTE] 22 | > After completing Exercise 1 you can either continue with your current code or start from the code template provided for you in subsequent exercises. 23 | 24 | ``` 25 | . 26 | ├── appendix -- Bonus exercise with the use of gdb for debugging MAMBO and target applications 27 | │   └── README.md 28 | ├── exercise1 -- The repository for Exercise 1 29 | │   ├── code 30 | │   │   └── tutorial.c 31 | │   ├── README.md 32 | │   └── solution 33 | │   └── solution.c 34 | ├── exercise2 -- The repository for Exercise 2 35 | │   ├── code 36 | │   │   └── tutorial.c 37 | │   ├── README.md 38 | │   └── solution 39 | │   └── solution.c 40 | ├── exercise3 -- The repository for Exercise 3 41 | │   ├── code 42 | │   │   └── tutorial.c 43 | │   ├── README.md 44 | │   └── solution 45 | │   └── solution.c 46 | ├── exercise4 -- The repository for Exercise 4 47 | │   ├── code 48 | │   │   └── tutorial.c 49 | │   ├── README.md 50 | │   └── solution 51 | │   └── solution.c 52 | ├── introduction -- The repository for Introduction 53 | │   ├── code 54 | │   │   ├── Makefile 55 | │   │   ├── test.c 56 | | | └── tutorial.c 57 | │   ├── mambo 58 | │   │   └── makefile 59 | │   └── README.md 60 | └── README.md 61 | 62 | ``` 63 | 64 | ## Introduction 65 | Follow the [link](introduction/README.md) to start with the Introduction. 66 | 67 | ## Exercise 1 - Callbacks and scan-time code analysis 68 | Follow the [link](exercise1/README.md) to start Exercise 1. 69 | 70 | ## Exercise 2 - Extending Scan-time Analysis 71 | Follow the [link](exercise2/README.md) to start Exercise 2. 72 | 73 | ## Exercise 3 - Run-time Instrumentation 74 | Follow the [link](exercise3/README.md) to start Exercise 3. 75 | 76 | ## Exercise 4 - Advanced Instrumentation 77 | Follow the [link](exercise4/README.md) to start Exercise 4. 78 | 79 | ## Appendix 80 | Follow the [link](appendix/README.md) to start the additional exercises. 81 | 82 | #### ✏️ Please help us improve the MAMBO tutorial by following the [link](https://forms.office.com/e/ZtDJSEgWhH). 83 | -------------------------------------------------------------------------------- /docs/tutorials/hipeac2024/appendix/README.md: -------------------------------------------------------------------------------- 1 | # Appendix 2 | The following will teach you how to debug both MAMBO and an application running under MAMBO, using gdb. This is a useful skill to have if you wish to contribute to the development of MAMBO, or are developing complex plugins. 3 | 4 | ## Pre-requisites 5 | You will need gdb installed on the system. 6 | 7 | ## Running MAMBO with gdb 8 | 1. Run MAMBO with gdb `gdb ./dbm`. Note that this launches gdb with the MAMBO binary. 9 | 2. Run the application under MAMBO after running gdb: `run binary-to-run`. For example, to run ls: `run /bin/ls`. 10 | 11 | > [!TIP] 12 | > Arguments for the application can be passed directly to `gdb` using the `--args` flag, e.g. `gdb --args ./dbm /bin/ls`. 13 | 14 | ## Setting a breakpoint within MAMBO 15 | To inspect MAMBO internals such as the scanner or dispatcher, simply set a breakpoint at the required line. For example, to break when scanning a new aarch64 basic block: `break arch/aarch64/scanner_a64.c:scan_a64`. Now run the application as before. 16 | 17 | You will now see gdb break within the scanner. 18 | 19 | To step through the scanner line by line, type: `layout src`. This will switch to a view displaying the source code. Step through using `n`. 20 | 21 | ## Inspecting a basic block 22 | You can find the start address of a basic block by stepping through the scanner as described above. 23 | Typing `print start_address` will print the starting address of the current basic block. Similarly, `print basic_block` will print the number of the current basic block being scanned. 24 | 25 | To inspect a basic block as it is constructed (or any other time), type `disassemble , +`. This will print out the instructions at this range of memory. 26 | 27 | Alternatively, you can follow execution out of the scanner and back into the code cache by stepping through instructions until you reach the code cache. Note, that there is no source code available to display here, because this code is not internal to MAMBO, rather it is generated by scanning basic blocks from the loaded binary. Type `layout asm` to switch to an assembler view of memory and step through the code cache using `ni` to step instruction by instruction. 28 | -------------------------------------------------------------------------------- /docs/tutorials/hipeac2024/exercise1/code/tutorial.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of MAMBO, a low-overhead dynamic binary modification tool: 3 | https://github.com/beehive-lab/mambo 4 | 5 | Copyright 2024 University of Manchester 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | #ifdef PLUGINS_NEW 21 | 22 | #include 23 | #include 24 | 25 | #include "../plugins.h" 26 | 27 | int tutorial_pre_thread_cb(mambo_context* ctx) { 28 | fprintf(stderr, "[DEBUG] Starting thread %d!\n", mambo_get_thread_id(ctx)); 29 | } 30 | 31 | int tutorial_post_thread_cb(mambo_context* ctx) { 32 | fprintf(stderr, "[DEBUG] Stopping thread %d!\n", mambo_get_thread_id(ctx)); 33 | } 34 | 35 | /* TODO: Add pre_basic_block_cb here. */ 36 | 37 | /* TODO: Add post_basic_block_cb here. */ 38 | 39 | __attribute__((constructor)) 40 | void init_tutorial() { 41 | mambo_context *ctx = mambo_register_plugin(); 42 | assert(ctx != NULL); 43 | 44 | mambo_register_pre_thread_cb(ctx, &tutorial_pre_thread_cb); 45 | mambo_register_post_thread_cb(ctx, &tutorial_post_thread_cb); 46 | 47 | /* TODO: Register *_basic_block_cb here. */ 48 | } 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /docs/tutorials/hipeac2024/exercise1/solution/solution.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of MAMBO, a low-overhead dynamic binary modification tool: 3 | https://github.com/beehive-lab/mambo 4 | 5 | Copyright 2024 University of Manchester 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | #ifdef PLUGINS_NEW 21 | 22 | #include 23 | #include 24 | 25 | #include "../plugins.h" 26 | 27 | int tutorial_pre_thread_cb(mambo_context* ctx) { 28 | fprintf(stderr, "[DEBUG] Starting thread %d!\n", mambo_get_thread_id(ctx)); 29 | } 30 | 31 | int tutorial_post_thread_cb(mambo_context* ctx) { 32 | fprintf(stderr, "[DEBUG] Stopping thread %d!\n", mambo_get_thread_id(ctx)); 33 | } 34 | 35 | int tutorial_pre_basic_block_cb(mambo_context* ctx) { 36 | void* source_addr = mambo_get_source_addr(ctx); 37 | 38 | fprintf(stderr, "Basic block starts at address: %p!\n", source_addr); 39 | } 40 | 41 | int tutorial_post_basic_block_cb(mambo_context* ctx) { 42 | void* source_addr = mambo_get_source_addr(ctx); 43 | 44 | fprintf(stderr, "Basic block ends at address: %p!\n", source_addr); 45 | } 46 | 47 | __attribute__((constructor)) 48 | void init_tutorial() { 49 | mambo_context *ctx = mambo_register_plugin(); 50 | assert(ctx != NULL); 51 | 52 | mambo_register_pre_thread_cb(ctx, &tutorial_pre_thread_cb); 53 | mambo_register_post_thread_cb(ctx, &tutorial_post_thread_cb); 54 | 55 | mambo_register_pre_basic_block_cb(ctx, &tutorial_pre_basic_block_cb); 56 | mambo_register_post_basic_block_cb(ctx, &tutorial_post_basic_block_cb); 57 | } 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /docs/tutorials/hipeac2024/exercise2/code/tutorial.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of MAMBO, a low-overhead dynamic binary modification tool: 3 | https://github.com/beehive-lab/mambo 4 | 5 | Copyright 2024 University of Manchester 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | #ifdef PLUGINS_NEW 21 | 22 | #include 23 | #include 24 | 25 | #include "../plugins.h" 26 | 27 | int tutorial_pre_thread_cb(mambo_context* ctx) { 28 | fprintf(stderr, "[DEBUG] Starting thread %d!\n", mambo_get_thread_id(ctx)); 29 | 30 | /* TODO: Allocate a new hash map and make it available to the whole plugin. */ 31 | } 32 | 33 | int tutorial_post_thread_cb(mambo_context* ctx) { 34 | fprintf(stderr, "[DEBUG] Stopping thread %d!\n", mambo_get_thread_id(ctx)); 35 | 36 | /* TODO: Print recorded basic blocks alongside the execution count and the symbol information. */ 37 | 38 | /* TODO: Free the hash map. */ 39 | } 40 | 41 | int tutorial_pre_basic_block_cb(mambo_context* ctx) { 42 | void* source_addr = mambo_get_source_addr(ctx); 43 | 44 | fprintf(stderr, "Basic block starts at address: %p!\n", source_addr); 45 | 46 | /* TODO: Add the block to the hash map or increment the counter if the block already exists. */ 47 | } 48 | 49 | int tutorial_post_basic_block_cb(mambo_context* ctx) { 50 | void* source_addr = mambo_get_source_addr(ctx); 51 | 52 | fprintf(stderr, "Basic block ends at address: %p!\n", source_addr); 53 | } 54 | 55 | __attribute__((constructor)) 56 | void init_tutorial() { 57 | mambo_context *ctx = mambo_register_plugin(); 58 | assert(ctx != NULL); 59 | 60 | mambo_register_pre_thread_cb(ctx, &tutorial_pre_thread_cb); 61 | mambo_register_post_thread_cb(ctx, &tutorial_post_thread_cb); 62 | 63 | mambo_register_pre_basic_block_cb(ctx, &tutorial_pre_basic_block_cb); 64 | mambo_register_post_basic_block_cb(ctx, &tutorial_post_basic_block_cb); 65 | } 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /docs/tutorials/hipeac2024/exercise3/README.md: -------------------------------------------------------------------------------- 1 | # Exercise 3: Run-time Instrumentation 2 | 3 | The purpose of this exercise is to introduce the user to the run-time binary instrumentation, as opposed to scan time analysis, and MAMBO instrumentation helpers. The specific task is: 4 | 5 | ___ 6 | **Replace the scan-time counter increment with run-time instrumentation: `emit_counter64_incr`.** 7 | ___ 8 | 9 | ## Step 1: MAMBO Helpers and `emit_counter64_incr` 10 | 11 | ### Scan-time vs Run-time Instrumentation 12 | 13 | So far all the code written within the plugin executed only once when the callback was called. This has been sufficient to find bounds of the executing basic blocks, however produced an incorrect result when counting the execution of those blocks. The reason is that, callbacks execute only when the binary is scanned, i.e. its code is copied into the code cache. Hence, the callback executes only once[^1] regardless of how many times the actual basic block or an instruction executes. 14 | 15 | To mitigate this issue the callback has to emit new instructions into the instruction stream in the code cache. In other words, the callback *instruments* basic blocks or instructions by adding extra code, that is executed every time that basic block or instruction executes. 16 | 17 | [^1]: In reality the callback may be re-executed when the code cache is flushed or optimised, however it is irrelevant in the context of this exercise. 18 | 19 | ### MAMBO Instrumentation Helpers 20 | 21 | MAMBO uses code instrumentation functions (helpers) to insert new code into the instruction stream of the basic block in the code cache. The helpers can be used to set registers, emit branches and function calls, create counters, preserve the application state, etc. This exercise focuses on one of the functions, described in the next section: `emit_counter64_incr`. 22 | 23 | > [!TIP] 24 | > You can find the full list of MAMBO helper functions in `$MAMBO_ROOT/api/helpers.h` 25 | 26 | ### Emitting Counter Instrumentation 27 | 28 | In this exercise, the following helper function for emitting a counter is used: 29 | 30 | ```c 31 | void emit_counter64_incr(mambo_context *ctx, void *counter, unsigned incr); 32 | ``` 33 | 34 | The function takes as it's arguments the MAMBO context, the memory location of the counter, and an unsigned integer that is added to the counter. 35 | 36 | For example: 37 | 38 | ```c 39 | emit_counter64_incr(ctx, counter, 1); 40 | ``` 41 | 42 | Replaces the incorrect: 43 | 44 | ```c 45 | *counter += 1; 46 | ``` 47 | 48 | > [!CAUTION] 49 | > Only heap allocated counters or global data counters should be passed to the helper, as any local stack data will be lost once the callback function returns. 50 | 51 | ### Tasks 52 | 53 | - [ ] Replace the scan time counter increment with appropriate instrumentation using `emit_counter64_incr`. 54 | 55 | ## Step 2: Evaluation 56 | 57 | Now, the `test` binary can be run with the modified plugin. Notice the output of the modified version of the plugin. The previously incorrect basic blocks count should display correct values. 58 | 59 | ## Next Steps 👏 60 | 61 | This is the end of Exercise 3. Feel free to ask us any questions or proceed to [Exercise 4](../exercise4/README.md). 62 | -------------------------------------------------------------------------------- /docs/tutorials/hipeac2024/introduction/README.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | The purpose of the Introduction is to go through the main directory of MAMBO, set up an empty plugin and compile and run a test application. 4 | 5 | ## Step 1: Setting up the `test` binary 6 | 7 | > [!IMPORTANT] 8 | > Before continuing make sure `MAMBO_ROOT` is correctly set by running `echo $MAMBO_ROOT`. If the path does not point to the root directory of MAMBO export it with: 9 | > 10 | > ```shell 11 | > export MAMBO_ROOT= 12 | > ``` 13 | 14 | We build the `test` application with `make`: 15 | 16 | ```shell 17 | cd $MAMBO_ROOT/docs/tutorials/hipeac2024/introduction/code 18 | make 19 | ``` 20 | 21 | > [!NOTE] 22 | > Do not change the makefile of the `test` binary. We compile it with `-O0` and `-g` to make analysis more interesting. 23 | 24 | ## Step 2: Build MAMBO with the plugin 25 | 26 | Copy the makefile from `$MAMBO_ROOT/tutorials/hipeac2024/introduction/mambo` to your MAMBO repository to replace the existing makefile. This file includes the new plugin into the build process. 27 | 28 | ```shell 29 | cp $MAMBO_ROOT/docs/tutorials/hipeac2024/introduction/mambo/makefile $MAMBO_ROOT 30 | ``` 31 | 32 | Then, copy the initial plugin template into `$MAMBO_ROOT/plugins/tutorial.c`: 33 | 34 | ```shell 35 | cp $MAMBO_ROOT/docs/tutorials/hipeac2024/introduction/code/tutorial.c $MAMBO_ROOT/plugins/ 36 | ``` 37 | 38 | Re-build MAMBO with the newly created plugin and the copied Makefile: 39 | 40 | ```shell 41 | cd $MAMBO_ROOT 42 | make 43 | ``` 44 | 45 | > [!TIP] 46 | > You can easily add/remove plugins from the MAMBO makefile with, for example: 47 | > 48 | > ``` 49 | > PLUGINS+=plugins/my_plugin.c plugins/my_plugin_helpers.c 50 | > ``` 51 | > 52 | > In `line 12` of the copied makefile, the new plugin was added in the same way. 53 | 54 | ## Step 3: Test the Target Application 55 | 56 | Run the `test` binary. 57 | 58 | ```shell 59 | ./dbm $MAMBO_ROOT/docs/tutorials/hipeac2024/introduction/code/test 60 | ``` 61 | 62 | > [!NOTE] 63 | > Binary should run under MAMBO and nothing unexpected should happen as plugin does not do anything. 64 | 65 | The expected output is: 66 | 67 | ``` 68 | 2^16 = 65536 69 | ``` 70 | 71 | Now it is a good time to look into the `test` application and see what it does. The code can be found in `$MAMBO_ROOT/docs/tutorials/hipeac2024/introduction/code/test.c`: 72 | 73 | ```c 74 | int main(int argc, char* argv[]) { 75 | int base = 2; 76 | int result = 1; 77 | for(int i = 0; i < 16; i++) { 78 | result *= base; 79 | } 80 | printf("2^16 = %d\n", result); 81 | } 82 | ``` 83 | 84 | The program simply calculates 2 to the power of 16 by using a repeated multiplication, and prints the result. When dynamically analysing the binary it should be expected for some parts of the code to run only once (e.g., `printf`), and for some to run 16 times (e.g., multiplication inside the loop). 85 | 86 | ## Next Steps 👏 87 | 88 | This is the end of Introduction. Feel free to ask us questions or proceed to [Exercise 1](../exercise1/README.md). 89 | -------------------------------------------------------------------------------- /docs/tutorials/hipeac2024/introduction/code/Makefile: -------------------------------------------------------------------------------- 1 | test: test.c 2 | cc -O0 -g test.c -o test 3 | -------------------------------------------------------------------------------- /docs/tutorials/hipeac2024/introduction/code/test.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char* argv[]) { 4 | int base = 2; 5 | int result = 1; 6 | for(int i = 0; i < 16; i++) { 7 | result *= base; 8 | } 9 | printf("2^16 = %d\n", result); 10 | } 11 | -------------------------------------------------------------------------------- /docs/tutorials/hipeac2024/introduction/code/tutorial.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of MAMBO, a low-overhead dynamic binary modification tool: 3 | https://github.com/beehive-lab/mambo 4 | 5 | Copyright 2024 University of Manchester 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | #ifdef PLUGINS_NEW 21 | 22 | #include 23 | #include 24 | 25 | #include "../plugins.h" 26 | 27 | __attribute__((constructor)) 28 | void init_tutorial() { 29 | mambo_context *ctx = mambo_register_plugin(); 30 | assert(ctx != NULL); 31 | } 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /docs/tutorials/hipeac2024/presentation.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beehive-lab/mambo/dcdf19a751092c18cccc1e31fea684dfc599c8b8/docs/tutorials/hipeac2024/presentation.pdf -------------------------------------------------------------------------------- /docs/tutorials/hipeac2025/README.md: -------------------------------------------------------------------------------- 1 | # MAMBO - Dynamic Binary Instrumentation on ARM and RISC-V 💻 Welcome!! 2 | 3 | ## Getting Started 4 | 5 | - Install Docker 6 | 7 | Visit the [link](https://github.com/beehive-lab/mambo/tree/master/docker) to find details about MAMBO on Docker. 8 | 9 | - Directory structure 10 | 11 | Each exercise contains the following folders: 12 | - `code`: This folder contains the template of the MAMBO plugin for each exercise that you need to modify/add code in the `TODO` sections. 13 | 14 | - `solution`: This folder contains the implemented MAMBO plugin for each exercise. 15 | 16 | > [!NOTE] 17 | > MAMBO can be also run natively, without Docker, on Armv8 Linux machines. Speak to us if you wish to do so and have any problems. 18 | 19 | Complete exercises in the following order: 20 | 21 | ## Introduction 22 | Follow the [link](introduction/README.md) to start with the Introduction. 23 | 24 | ## Exercise 1 - Callbacks and scan-time code analysis 25 | Follow the [link](exercise1/README.md) to start Exercise 1. 26 | 27 | ## Exercise 2 - Extending Scan-time Analysis 28 | Follow the [link](exercise2/README.md) to start Exercise 2. 29 | 30 | ## Exercise 3 - Run-time Instrumentation 31 | Follow the [link](exercise3/README.md) to start Exercise 3. 32 | 33 | ## Exercise 4 - Advanced Instrumentation 34 | Follow the [link](exercise4/README.md) to start Exercise 4. 35 | 36 | ## Appendix 37 | Follow the [link](appendix/README.md) to start the additional exercises. 38 | 39 | > [!NOTE] 40 | > After completing Exercise 1 you can either continue with your current code or start from the code template provided for you in subsequent exercises. 41 | 42 | ``` 43 | . 44 | ├── appendix -- Bonus exercise with the use of gdb for debugging MAMBO and target applications 45 | │   └── README.md 46 | ├── exercise1 -- The repository for Exercise 1 47 | │   ├── code 48 | │   │   └── tutorial.c 49 | │   ├── README.md 50 | │   └── solution 51 | │   └── solution.c 52 | ├── exercise2 -- The repository for Exercise 2 53 | │   ├── code 54 | │   │   └── tutorial.c 55 | │   ├── README.md 56 | │   └── solution 57 | │   └── solution.c 58 | ├── exercise3 -- The repository for Exercise 3 59 | │   ├── code 60 | │   │   └── tutorial.c 61 | │   ├── README.md 62 | │   └── solution 63 | │   └── solution.c 64 | ├── exercise4 -- The repository for Exercise 4 65 | │   ├── code 66 | │   │   └── tutorial.c 67 | │   ├── README.md 68 | │   └── solution 69 | │   └── solution.c 70 | ├── introduction -- The repository for Introduction 71 | │   ├── code 72 | │   │   ├── Makefile 73 | │   │   ├── test.c 74 | | | └── tutorial.c 75 | │   ├── mambo 76 | │   │   └── makefile 77 | │   └── README.md 78 | └── README.md 79 | 80 | ``` 81 | 82 | -------------------------------------------------------------------------------- /docs/tutorials/hipeac2025/appendix/README.md: -------------------------------------------------------------------------------- 1 | # Appendix 2 | The following will teach you how to debug both MAMBO and an application running under MAMBO, using gdb. This is a useful skill to have if you wish to contribute to the development of MAMBO, or are developing complex plugins. 3 | 4 | ## Pre-requisites 5 | You will need gdb installed on the system. 6 | 7 | ## Running MAMBO with gdb 8 | 1. Run MAMBO with gdb `gdb ./dbm`. Note that this launches gdb with the MAMBO binary. 9 | 2. Run the application under MAMBO after running gdb: `run binary-to-run`. For example, to run ls: `run /bin/ls`. 10 | 11 | > [!TIP] 12 | > Arguments for the application can be passed directly to `gdb` using the `--args` flag, e.g. `gdb --args ./dbm /bin/ls`. 13 | 14 | ## Setting a breakpoint within MAMBO 15 | To inspect MAMBO internals such as the scanner or dispatcher, simply set a breakpoint at the required line. For example, to break when scanning a new aarch64 basic block: `break arch/aarch64/scanner_a64.c:scan_a64`. Now run the application as before. 16 | 17 | You will now see gdb break within the scanner. 18 | 19 | To step through the scanner line by line, type: `layout src`. This will switch to a view displaying the source code. Step through using `n`. 20 | 21 | ## Inspecting a basic block 22 | You can find the start address of a basic block by stepping through the scanner as described above. 23 | Typing `print start_address` will print the starting address of the current basic block. Similarly, `print basic_block` will print the number of the current basic block being scanned. 24 | 25 | To inspect a basic block as it is constructed (or any other time), type `disassemble , +`. This will print out the instructions at this range of memory. 26 | 27 | Alternatively, you can follow execution out of the scanner and back into the code cache by stepping through instructions until you reach the code cache. Note, that there is no source code available to display here, because this code is not internal to MAMBO, rather it is generated by scanning basic blocks from the loaded binary. Type `layout asm` to switch to an assembler view of memory and step through the code cache using `ni` to step instruction by instruction. 28 | -------------------------------------------------------------------------------- /docs/tutorials/hipeac2025/exercise1/code/tutorial.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of MAMBO, a low-overhead dynamic binary modification tool: 3 | https://github.com/beehive-lab/mambo 4 | 5 | Copyright 2024 University of Manchester 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | #ifdef PLUGINS_NEW 21 | 22 | #include 23 | #include 24 | 25 | #include "../plugins.h" 26 | 27 | int tutorial_pre_thread_cb(mambo_context* ctx) { 28 | fprintf(stderr, "[DEBUG] Starting thread %d!\n", mambo_get_thread_id(ctx)); 29 | } 30 | 31 | int tutorial_post_thread_cb(mambo_context* ctx) { 32 | fprintf(stderr, "[DEBUG] Stopping thread %d!\n", mambo_get_thread_id(ctx)); 33 | } 34 | 35 | /* TODO: Add pre_basic_block_cb here. */ 36 | 37 | /* TODO: Add post_basic_block_cb here. */ 38 | 39 | __attribute__((constructor)) 40 | void init_tutorial() { 41 | mambo_context *ctx = mambo_register_plugin(); 42 | assert(ctx != NULL); 43 | 44 | mambo_register_pre_thread_cb(ctx, &tutorial_pre_thread_cb); 45 | mambo_register_post_thread_cb(ctx, &tutorial_post_thread_cb); 46 | 47 | /* TODO: Register *_basic_block_cb here. */ 48 | } 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /docs/tutorials/hipeac2025/exercise1/solution/solution.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of MAMBO, a low-overhead dynamic binary modification tool: 3 | https://github.com/beehive-lab/mambo 4 | 5 | Copyright 2024 University of Manchester 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | #ifdef PLUGINS_NEW 21 | 22 | #include 23 | #include 24 | 25 | #include "../plugins.h" 26 | 27 | int tutorial_pre_thread_cb(mambo_context* ctx) { 28 | fprintf(stderr, "[DEBUG] Starting thread %d!\n", mambo_get_thread_id(ctx)); 29 | } 30 | 31 | int tutorial_post_thread_cb(mambo_context* ctx) { 32 | fprintf(stderr, "[DEBUG] Stopping thread %d!\n", mambo_get_thread_id(ctx)); 33 | } 34 | 35 | int tutorial_pre_basic_block_cb(mambo_context* ctx) { 36 | void* source_addr = mambo_get_source_addr(ctx); 37 | 38 | fprintf(stderr, "Basic block starts at address: %p!\n", source_addr); 39 | } 40 | 41 | int tutorial_post_basic_block_cb(mambo_context* ctx) { 42 | void* source_addr = mambo_get_source_addr(ctx); 43 | 44 | fprintf(stderr, "Basic block ends at address: %p!\n", source_addr); 45 | } 46 | 47 | __attribute__((constructor)) 48 | void init_tutorial() { 49 | mambo_context *ctx = mambo_register_plugin(); 50 | assert(ctx != NULL); 51 | 52 | mambo_register_pre_thread_cb(ctx, &tutorial_pre_thread_cb); 53 | mambo_register_post_thread_cb(ctx, &tutorial_post_thread_cb); 54 | 55 | mambo_register_pre_basic_block_cb(ctx, &tutorial_pre_basic_block_cb); 56 | mambo_register_post_basic_block_cb(ctx, &tutorial_post_basic_block_cb); 57 | } 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /docs/tutorials/hipeac2025/exercise2/code/tutorial.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of MAMBO, a low-overhead dynamic binary modification tool: 3 | https://github.com/beehive-lab/mambo 4 | 5 | Copyright 2024 University of Manchester 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | #ifdef PLUGINS_NEW 21 | 22 | #include 23 | #include 24 | 25 | #include "../plugins.h" 26 | 27 | int tutorial_pre_thread_cb(mambo_context* ctx) { 28 | fprintf(stderr, "[DEBUG] Starting thread %d!\n", mambo_get_thread_id(ctx)); 29 | 30 | /* TODO: Allocate a new hash map and make it available to the whole plugin. */ 31 | } 32 | 33 | int tutorial_post_thread_cb(mambo_context* ctx) { 34 | fprintf(stderr, "[DEBUG] Stopping thread %d!\n", mambo_get_thread_id(ctx)); 35 | 36 | /* TODO: Print recorded basic blocks alongside the execution count and the symbol information. */ 37 | 38 | /* TODO: Free the hash map. */ 39 | } 40 | 41 | int tutorial_pre_basic_block_cb(mambo_context* ctx) { 42 | void* source_addr = mambo_get_source_addr(ctx); 43 | 44 | fprintf(stderr, "Basic block starts at address: %p!\n", source_addr); 45 | 46 | /* TODO: Add the block to the hash map or increment the counter if the block already exists. */ 47 | } 48 | 49 | int tutorial_post_basic_block_cb(mambo_context* ctx) { 50 | void* source_addr = mambo_get_source_addr(ctx); 51 | 52 | fprintf(stderr, "Basic block ends at address: %p!\n", source_addr); 53 | } 54 | 55 | __attribute__((constructor)) 56 | void init_tutorial() { 57 | mambo_context *ctx = mambo_register_plugin(); 58 | assert(ctx != NULL); 59 | 60 | mambo_register_pre_thread_cb(ctx, &tutorial_pre_thread_cb); 61 | mambo_register_post_thread_cb(ctx, &tutorial_post_thread_cb); 62 | 63 | mambo_register_pre_basic_block_cb(ctx, &tutorial_pre_basic_block_cb); 64 | mambo_register_post_basic_block_cb(ctx, &tutorial_post_basic_block_cb); 65 | } 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /docs/tutorials/hipeac2025/exercise3/README.md: -------------------------------------------------------------------------------- 1 | # Exercise 3: Run-time Instrumentation 2 | 3 | The purpose of this exercise is to introduce the user to the run-time binary instrumentation, as opposed to scan time analysis, and MAMBO instrumentation helpers. The specific task is: 4 | 5 | ___ 6 | **Replace the scan-time counter increment with run-time instrumentation: `emit_counter64_incr`.** 7 | ___ 8 | 9 | ## Step 1: MAMBO Helpers and `emit_counter64_incr` 10 | 11 | ### Scan-time vs Run-time Instrumentation 12 | 13 | So far all the code written within the plugin executed only once when the callback was called. This has been sufficient to find bounds of the executing basic blocks, however produced an incorrect result when counting the execution of those blocks. The reason is that, callbacks execute only when the binary is scanned, i.e. its code is copied into the code cache. Hence, the callback executes only once[^1] regardless of how many times the actual basic block or an instruction executes. 14 | 15 | To mitigate this issue the callback has to emit new instructions into the instruction stream in the code cache. In other words, the callback *instruments* basic blocks or instructions by adding extra code, that is executed every time that basic block or instruction executes. 16 | 17 | [^1]: In reality the callback may be re-executed when the code cache is flushed or optimised, however it is irrelevant in the context of this exercise. 18 | 19 | ### MAMBO Instrumentation Helpers 20 | 21 | MAMBO uses code instrumentation functions (helpers) to insert new code into the instruction stream of the basic block in the code cache. The helpers can be used to set registers, emit branches and function calls, create counters, preserve the application state, etc. This exercise focuses on one of the functions, described in the next section: `emit_counter64_incr`. 22 | 23 | > [!TIP] 24 | > You can find the full list of MAMBO helper functions in `$MAMBO_ROOT/api/helpers.h` 25 | 26 | ### Emitting Counter Instrumentation 27 | 28 | In this exercise, the following helper function for emitting a counter is used: 29 | 30 | ```c 31 | void emit_counter64_incr(mambo_context *ctx, void *counter, unsigned incr); 32 | ``` 33 | 34 | The function takes as it's arguments the MAMBO context, the memory location of the counter, and an unsigned integer that is added to the counter. 35 | 36 | For example: 37 | 38 | ```c 39 | emit_counter64_incr(ctx, counter, 1); 40 | ``` 41 | 42 | Replaces the incorrect: 43 | 44 | ```c 45 | *counter += 1; 46 | ``` 47 | 48 | > [!CAUTION] 49 | > Only heap allocated counters or global data counters should be passed to the helper, as any local stack data will be lost once the callback function returns. 50 | 51 | ### Tasks 52 | 53 | - [ ] Replace the scan time counter increment with appropriate instrumentation using `emit_counter64_incr`. 54 | 55 | ## Step 2: Evaluation 56 | 57 | Now, the `test` binary can be run with the modified plugin. Notice the output of the modified version of the plugin. The previously incorrect basic blocks count should display correct values. Note that you will see a large number of basic blocks because this includes basic blocks from pre-main and post-main execution such as libc. 58 | 59 | ## Next Steps 👏 60 | 61 | This is the end of Exercise 3. Feel free to ask us any questions or proceed to [Exercise 4](../exercise4/README.md). 62 | -------------------------------------------------------------------------------- /docs/tutorials/hipeac2025/introduction/README.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | The purpose of the Introduction is to go through the main directory of MAMBO, set up an empty plugin and compile and run a test application. 4 | 5 | ## Step 1: Setting up the `test` binary 6 | 7 | > [!IMPORTANT] 8 | > Before continuing make sure `MAMBO_ROOT` is correctly set by running `echo $MAMBO_ROOT`. If the path does not point to the root directory of MAMBO export it with: 9 | > 10 | > ```shell 11 | > export MAMBO_ROOT= 12 | > ``` 13 | 14 | We build the `test` application with `make`: 15 | 16 | ```shell 17 | cd $MAMBO_ROOT/docs/tutorials/hipeac2025/introduction/code 18 | make 19 | ``` 20 | 21 | > [!NOTE] 22 | > Do not change the makefile of the `test` binary. We compile it with `-O0` and `-g` to make analysis more interesting. 23 | 24 | ## Step 2: Build MAMBO with the plugin 25 | 26 | Copy line 13: `PLUGINS+=plugins/tutorial.c` of the makefile from `$MAMBO_ROOT/docs/tutorials/hipeac2025/introduction/mambo` to the makefile in your MAMBO repository. This includes the new plugin into the build process. 27 | 28 | Then, copy the initial plugin template into `$MAMBO_ROOT/plugins/tutorial.c`: 29 | 30 | ```shell 31 | cp $MAMBO_ROOT/docs/tutorials/hipeac2025/introduction/code/tutorial.c $MAMBO_ROOT/plugins/ 32 | ``` 33 | 34 | Re-build MAMBO with the newly created plugin and the copied Makefile: 35 | 36 | ```shell 37 | cd $MAMBO_ROOT 38 | make 39 | ``` 40 | 41 | > [!TIP] 42 | > You can easily add/remove plugins from the MAMBO makefile with, for example: 43 | > 44 | > ``` 45 | > PLUGINS+=plugins/my_plugin.c plugins/my_plugin_helpers.c 46 | > ``` 47 | > 48 | > In `line 12` of the copied makefile, the new plugin was added in the same way. 49 | 50 | ## Step 3: Test the Target Application 51 | 52 | Run the `test` binary. 53 | 54 | ```shell 55 | ./dbm $MAMBO_ROOT/docs/tutorials/hipeac2025/introduction/code/test 56 | ``` 57 | 58 | > [!NOTE] 59 | > Binary should run under MAMBO and nothing unexpected should happen as plugin does not do anything. 60 | 61 | The expected output is: 62 | 63 | ``` 64 | 2^16 = 65536 65 | ``` 66 | 67 | Now it is a good time to look into the `test` application and see what it does. The code can be found in `$MAMBO_ROOT/docs/tutorials/hipeac2025/introduction/code/test.c`: 68 | 69 | ```c 70 | int main(int argc, char* argv[]) { 71 | int base = 2; 72 | int result = 1; 73 | for(int i = 0; i < 16; i++) { 74 | result *= base; 75 | } 76 | printf("2^16 = %d\n", result); 77 | } 78 | ``` 79 | 80 | The program simply calculates 2 to the power of 16 by using a repeated multiplication, and prints the result. When dynamically analysing the binary it should be expected for some parts of the code to run only once (e.g., `printf`), and for some to run 16 times (e.g., multiplication inside the loop). 81 | 82 | ## Next Steps 👏 83 | 84 | This is the end of Introduction. Feel free to ask us questions or proceed to [Exercise 1](../exercise1/README.md). 85 | -------------------------------------------------------------------------------- /docs/tutorials/hipeac2025/introduction/code/Makefile: -------------------------------------------------------------------------------- 1 | test: test.c 2 | cc -O0 -g test.c -o test 3 | -------------------------------------------------------------------------------- /docs/tutorials/hipeac2025/introduction/code/test.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char* argv[]) { 4 | int base = 2; 5 | int result = 1; 6 | for(int i = 0; i < 16; i++) { 7 | result *= base; 8 | } 9 | printf("2^16 = %d\n", result); 10 | } 11 | -------------------------------------------------------------------------------- /docs/tutorials/hipeac2025/introduction/code/tutorial.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of MAMBO, a low-overhead dynamic binary modification tool: 3 | https://github.com/beehive-lab/mambo 4 | 5 | Copyright 2024 University of Manchester 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | #ifdef PLUGINS_NEW 21 | 22 | #include 23 | #include 24 | 25 | #include "../plugins.h" 26 | 27 | __attribute__((constructor)) 28 | void init_tutorial() { 29 | mambo_context *ctx = mambo_register_plugin(); 30 | assert(ctx != NULL); 31 | } 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /docs/tutorials/start-guide/README.md: -------------------------------------------------------------------------------- 1 | ## Introduction :wave: 2 | 3 | Welcome to the start guide for MAMBO! 4 | 5 | This tutorial introduces MAMBO and the fundamental concepts of Dynamic Binary Modification frameworks. 6 | 7 | ### Exercises 8 | 9 | 0. [**Setting up your environment**](exercise0/README.md) 10 | - Installation 11 | - Environment Variables 12 | 1. [**Introduction to Dynamic Binary Modification**](exercise1/README.md) 13 | - Building a simple program 14 | - Dynamic Binary Modification 15 | 2. [**How MAMBO Works**](exercise2/README.md) 16 | - MAMBO Explained 17 | - Optimisations 18 | - Plugins 19 | 3. *Building a Simple Plugin (TODO)* 20 | - *Introduction to MAMBO plugins (TODO)* 21 | - *Context for building a plugin (TODO)* 22 | - *Writing the simple plugin (TODO)* 23 | - *Instrumenting into the basic block (TODO)* 24 | 4. *Building an Advanced Plugin (TODO)* 25 | - *Building an advanced plugin for a simple program (TODO)* 26 | 27 | ### Getting Started 28 | 29 | This start guide is linear, so to get started, follow the link to [Exercise 0](exercise0/README.md). 30 | 31 | ### References 32 | 33 | [Cosmin's DBM Thesis](https://www.proquest.com/docview/2022986300?pq-origsite=gscholar&fromopenview=true&sourcetype=Dissertations%20&%20Theses) 34 | 35 | [MAMBO Paper](https://dl.acm.org/doi/abs/10.1145/2896451) 36 | 37 | [Original MAMBO Tutorial](https://github.com/beehive-lab/mambo/tree/master/docs/tutorials/hipeac2024) 38 | 39 | -------------------------------------------------------------------------------- /docs/tutorials/start-guide/exercise0/README.md: -------------------------------------------------------------------------------- 1 | # Exercise 0: Setting up your environment 2 | 3 | ## 0.1: Installation 4 | 5 | There are two options for setting up MAMBO, either you can run it natively on physical/virtual ARMv8 Linux machines (including Apple Silicon), or you can virtualise the environment. 6 | 7 | ### Docker Container & Qemu 8 | 9 | For running in Docker, please follow this [guide](https://github.com/beehive-lab/mambo/tree/master/docker). In this guide, you are shown to create a docker container, which runs a QEMU instance for that can emulate a RISCV/ARM-64 machine running Ubuntu. From here, you can run MAMBO: 10 | 11 | **Your Local Machine** :arrow_right: Docker :arrow_right: Qemu (RISCV/ARM-64 Machine) :arrow_right: Ubuntu :arrow_right: **MAMBO** 12 | 13 | ### Native ARMv8 14 | 15 | If you can run MAMBO natively, first install its dependencies: 16 | 17 | ```console 18 | sudo apt-get install build-essential libelf-dev ruby 19 | ``` 20 | 21 | Then clone MAMBO: 22 | 23 | ```console 24 | git clone https://github.com/beehive-lab/mambo.git 25 | ``` 26 | 27 | ## 0.2: Environment Variables 28 | 29 | Before we continue, make sure you have the following environment variables set-up: 30 | 31 | ```console 32 | export MAMBO_ROOT= 33 | export START_GUIDE=$MAMBO_ROOT"/docs/tutorials/start-guide" 34 | ``` 35 | 36 | That's all there is to it. Now, let's get started and move on to [Exercise 1 ➡️](../exercise1/README.md) 37 | 38 | -------------------------------------------------------------------------------- /docs/tutorials/start-guide/exercise2/images/Context_Flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beehive-lab/mambo/dcdf19a751092c18cccc1e31fea684dfc599c8b8/docs/tutorials/start-guide/exercise2/images/Context_Flow.png -------------------------------------------------------------------------------- /docs/tutorials/start-guide/exercise2/images/ELF-File.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beehive-lab/mambo/dcdf19a751092c18cccc1e31fea684dfc599c8b8/docs/tutorials/start-guide/exercise2/images/ELF-File.png -------------------------------------------------------------------------------- /docs/tutorials/start-guide/exercise2/images/ELF-Loader.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beehive-lab/mambo/dcdf19a751092c18cccc1e31fea684dfc599c8b8/docs/tutorials/start-guide/exercise2/images/ELF-Loader.png -------------------------------------------------------------------------------- /docs/tutorials/start-guide/exercise2/images/Memory-Allocation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beehive-lab/mambo/dcdf19a751092c18cccc1e31fea684dfc599c8b8/docs/tutorials/start-guide/exercise2/images/Memory-Allocation.png -------------------------------------------------------------------------------- /docs/tutorials/start-guide/exercise2/images/Scanner-Code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beehive-lab/mambo/dcdf19a751092c18cccc1e31fea684dfc599c8b8/docs/tutorials/start-guide/exercise2/images/Scanner-Code.png -------------------------------------------------------------------------------- /docs/tutorials/start-guide/exercise2/images/Syscall_Signal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beehive-lab/mambo/dcdf19a751092c18cccc1e31fea684dfc599c8b8/docs/tutorials/start-guide/exercise2/images/Syscall_Signal.png -------------------------------------------------------------------------------- /docs/tutorials/start-guide/exercise2/images/basic-block.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beehive-lab/mambo/dcdf19a751092c18cccc1e31fea684dfc599c8b8/docs/tutorials/start-guide/exercise2/images/basic-block.png -------------------------------------------------------------------------------- /docs/tutorials/start-guide/exercise2/images/branch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beehive-lab/mambo/dcdf19a751092c18cccc1e31fea684dfc599c8b8/docs/tutorials/start-guide/exercise2/images/branch.png -------------------------------------------------------------------------------- /docs/tutorials/start-guide/exercise2/images/cache-dipatcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beehive-lab/mambo/dcdf19a751092c18cccc1e31fea684dfc599c8b8/docs/tutorials/start-guide/exercise2/images/cache-dipatcher.png -------------------------------------------------------------------------------- /docs/tutorials/start-guide/exercise2/images/empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beehive-lab/mambo/dcdf19a751092c18cccc1e31fea684dfc599c8b8/docs/tutorials/start-guide/exercise2/images/empty.png -------------------------------------------------------------------------------- /docs/tutorials/start-guide/exercise2/images/plugins.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beehive-lab/mambo/dcdf19a751092c18cccc1e31fea684dfc599c8b8/docs/tutorials/start-guide/exercise2/images/plugins.png -------------------------------------------------------------------------------- /docs/tutorials/start-guide/exercise2/images/syscall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beehive-lab/mambo/dcdf19a751092c18cccc1e31fea684dfc599c8b8/docs/tutorials/start-guide/exercise2/images/syscall.png -------------------------------------------------------------------------------- /docs/tutorials/start-guide/simple_program.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char* argv[]) { 4 | int base = 2; 5 | int result = 1; 6 | for(int i = 0; i < 16; i++) { 7 | result *= base; 8 | } 9 | printf("2^16 = %d\n", result); 10 | } -------------------------------------------------------------------------------- /elf/elf_loader.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of MAMBO, a low-overhead dynamic binary modification tool: 3 | https://github.com/beehive-lab/mambo 4 | 5 | Copyright 2013-2016 Cosmin Gorgovan 6 | Copyright 2017-2020 The University of Manchester 7 | 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | */ 20 | 21 | #include 22 | 23 | #ifdef __arm__ 24 | #define ELF_CLASS ELFCLASS32 25 | #define EM_MACHINE EM_ARM 26 | #define ELF_EHDR Elf32_Ehdr 27 | #define ELF_PHDR Elf32_Phdr 28 | #define ELF_GETEHDR(...) elf32_getehdr(__VA_ARGS__) 29 | #define ELF_GETPHDR(...) elf32_getphdr(__VA_ARGS__) 30 | #define ELF_AUXV_T Elf32_auxv_t 31 | #endif 32 | #ifdef __aarch64__ 33 | #define ELF_CLASS ELFCLASS64 34 | #define EM_MACHINE EM_AARCH64 35 | #define ELF_EHDR Elf64_Ehdr 36 | #define ELF_PHDR Elf64_Phdr 37 | #define ELF_GETEHDR(...) elf64_getehdr(__VA_ARGS__) 38 | #define ELF_GETPHDR(...) elf64_getphdr(__VA_ARGS__) 39 | #define ELF_AUXV_T Elf64_auxv_t 40 | #endif 41 | #ifdef __riscv 42 | #if __riscv_xlen == 32 43 | #define ELF_CLASS ELFCLASS32 44 | #define EM_MACHINE EM_RISCV 45 | #define ELF_EHDR Elf32_Ehdr 46 | #define ELF_PHDR Elf32_Phdr 47 | #define ELF_GETEHDR(...) elf32_getehdr(__VA_ARGS__) 48 | #define ELF_GETPHDR(...) elf32_getphdr(__VA_ARGS__) 49 | #define ELF_AUXV_T Elf32_auxv_t 50 | #endif 51 | #if __riscv_xlen == 64 52 | #define ELF_CLASS ELFCLASS64 53 | #define EM_MACHINE EM_RISCV 54 | #define ELF_EHDR Elf64_Ehdr 55 | #define ELF_PHDR Elf64_Phdr 56 | #define ELF_GETEHDR(...) elf64_getehdr(__VA_ARGS__) 57 | #define ELF_GETPHDR(...) elf64_getphdr(__VA_ARGS__) 58 | #define ELF_AUXV_T Elf64_auxv_t 59 | #endif 60 | #if __riscv_xlen == 128 61 | #error "Risc-V 128-bit no implemented" 62 | #endif 63 | #endif 64 | 65 | 66 | struct elf_loader_auxv { 67 | uintptr_t at_base; 68 | uintptr_t at_entry; 69 | uintptr_t at_phdr; 70 | uintptr_t at_phnum; 71 | }; 72 | 73 | void load_elf(char *filename, Elf **ret_elf, struct elf_loader_auxv *auxv, uintptr_t *entry_addr, bool is_interp); 74 | void elf_run(uintptr_t entry_address, char *filename, int argc, char **argv, char **envp, struct elf_loader_auxv *auxv); 75 | 76 | -------------------------------------------------------------------------------- /kernel_sigaction.h: -------------------------------------------------------------------------------- 1 | /* This is the sigaction structure from the Linux 2.1.20 kernel. */ 2 | 3 | #define HAVE_SA_RESTORER 4 | 5 | struct old_kernel_sigaction { 6 | __sighandler_t k_sa_handler; 7 | unsigned long sa_mask; 8 | unsigned long sa_flags; 9 | void (*sa_restorer) (void); 10 | }; 11 | 12 | /* This is the sigaction structure from the Linux 2.1.68 kernel. */ 13 | 14 | struct kernel_sigaction { 15 | __sighandler_t k_sa_handler; 16 | unsigned long sa_flags; 17 | void (*sa_restorer) (void); 18 | sigset_t sa_mask; 19 | }; 20 | -------------------------------------------------------------------------------- /pie/.gitignore: -------------------------------------------------------------------------------- 1 | *.c 2 | *.h 3 | *.o 4 | -------------------------------------------------------------------------------- /pie/generate_common.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | 3 | This file is part of PIE, an instruction encoder / decoder generator: 4 | https://github.com/beehive-lab/pie 5 | 6 | Copyright 2011-2016 Cosmin Gorgovan 7 | Copyright 2017-2021 The University of Manchester 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | Unless required by applicable law or agreed to in writing, software 16 | distributed under the License is distributed on an "AS IS" BASIS, 17 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | See the License for the specific language governing permissions and 19 | limitations under the License. 20 | 21 | =end 22 | 23 | def process_insts(filename, swaphw = false) 24 | process_file(filename, true, swaphw) 25 | end 26 | 27 | def process_all(filename, swaphw = false) 28 | process_file(filename, false, swaphw) 29 | end 30 | 31 | def do_swaphw(encoding) 32 | return encoding[16..31] + encoding[0..15] if encoding.size == 32 33 | return encoding 34 | end 35 | 36 | def process_file(filename, insts_only = false, swaphw = false) 37 | insts = [] 38 | 39 | File.readlines(filename).each do |raw_line| 40 | raw_line.strip! 41 | if raw_line.empty? 42 | break if insts_only 43 | next 44 | end 45 | next if raw_line[0] == '#' 46 | raw_line = raw_line.split('#')[0] 47 | line = raw_line.split(/[, ]+/) 48 | 49 | inst = Hash.new 50 | inst[:name] = line[0] 51 | 52 | inst[:bitmap] = "" 53 | i = 1 54 | while (line[i] and !line[i].include?(':')) 55 | inst[:bitmap] += line[i].strip 56 | i += 1 57 | end 58 | 59 | inst[:fields] = {} 60 | (i...line.size).each do |i| 61 | field = line[i].split(':') 62 | inst[:fields][field[0]] = {} 63 | inst[:fields][field[0]][:name] = field[1].strip 64 | if field[2] 65 | case field[2] 66 | when "!" 67 | cond = :diff 68 | when "=" 69 | cond = :eq 70 | else 71 | abort "Unsupported condition: #{field[2][0]} on line: #{line}" 72 | end 73 | inst[:fields][field[0]][:cond] = cond 74 | inst[:fields][field[0]][:cond_vals] = field[3..-1].map {|v| v.to_i(2)} 75 | end 76 | end 77 | 78 | # check that all fields have been defined 79 | inst[:bitmap].each_char do |f| 80 | unless f == '0' or f == '1' or inst[:fields][f] 81 | warn "Error: field #{f} not defined for #{inst[:name]}" 82 | warn raw_line 83 | abort 84 | end 85 | end 86 | 87 | if swaphw 88 | inst[:bitmap] = do_swaphw(inst[:bitmap]) 89 | end 90 | 91 | insts.push inst 92 | end 93 | 94 | return insts 95 | end 96 | 97 | def inst_len_to_cptr(len) 98 | case len 99 | when 16 100 | c_ptr = "uint16_t" 101 | when 32 102 | c_ptr = "uint32_t" 103 | else 104 | abort "Unknown instruction word width: #{len}" 105 | end 106 | return c_ptr 107 | end 108 | 109 | def get_min_inst_len(insts) 110 | min = 99999 111 | insts.each do |inst| 112 | min = inst[:bitmap].size if inst[:bitmap].size < min 113 | end 114 | return min 115 | end 116 | 117 | def get_max_inst_len(insts) 118 | max = 0 119 | insts.each do |inst| 120 | max = inst[:bitmap].size if inst[:bitmap].size > max 121 | end 122 | return max 123 | end 124 | 125 | def get_field_shift(bitmap, label) 126 | bitmap.size - bitmap.rindex(label) - 1 127 | end 128 | 129 | def get_field_mask(bitmap, label) 130 | width = bitmap.rindex(label) - bitmap.index(label) + 1 131 | return "0x" + ((1 << width) -1).to_s(16) 132 | end 133 | -------------------------------------------------------------------------------- /pie/generate_field-decoder.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | 3 | This file is part of PIE, an instruction encoder / decoder generator: 4 | https://github.com/beehive-lab/pie 5 | 6 | Copyright 2011-2016 Cosmin Gorgovan 7 | Copyright 2017-2021 The University of Manchester 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | Unless required by applicable law or agreed to in writing, software 16 | distributed under the License is distributed on an "AS IS" BASIS, 17 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | See the License for the specific language governing permissions and 19 | limitations under the License. 20 | 21 | =end 22 | 23 | require './generate_common.rb' 24 | 25 | def generate_f_prot(inst, inst_len) 26 | prot = "void #{ARGV[0]}_#{inst[:name]}_decode_fields" 27 | prot += " (\n" 28 | prot += "\t#{inst_len_to_cptr(inst_len)} *address" 29 | 30 | inst[:fields].each_pair do |field_label, field| 31 | next if field[:name] == "auto_cond" 32 | prot += ",\n\tunsigned int *#{field[:name]}" 33 | end 34 | 35 | prot += ")" 36 | 37 | return prot 38 | end 39 | 40 | def generate_f_body(inst, def_inst_len, swaphw) 41 | body = "\n{\n" 42 | 43 | if (inst[:bitmap].size == def_inst_len) 44 | body += "\t#{inst_len_to_cptr(inst[:bitmap].size)} instruction = *address;\n" 45 | elsif (inst[:bitmap].size == def_inst_len * 2) 46 | if (swaphw) 47 | body += "\t#{inst_len_to_cptr(inst[:bitmap].size)} instruction = (*(address + 1) << #{def_inst_len}) | *address;\n" 48 | else 49 | body += "\t#{inst_len_to_cptr(inst[:bitmap].size)} instruction = (*address << #{def_inst_len}) | *(address + 1);\n" 50 | end 51 | else 52 | abort "Unknown instruction inst word length" 53 | end 54 | 55 | inst[:fields].each_pair do |label, field| 56 | next if field[:name] == "auto_cond" 57 | shift = get_field_shift(inst[:bitmap], label) 58 | mask = get_field_mask(inst[:bitmap], label) 59 | body += "\t*#{field[:name]} = (instruction >> #{shift}) & #{mask};\n" 60 | end 61 | 62 | body += "}" 63 | 64 | return body 65 | end 66 | 67 | def generate_field_decoder(insts, inst_len, is_header, swaphw) 68 | insts.each do |inst| 69 | # skip instructions with no arguments 70 | next if inst[:fields].size == 0 or (inst[:fields].size == 1 && inst[:fields].first[1][:name] == "auto_cond") 71 | print generate_f_prot(inst, inst_len) 72 | puts ";" if is_header 73 | puts generate_f_body(inst, inst_len, swaphw) unless is_header 74 | end 75 | end 76 | 77 | def generate_header(insts, inst_len) 78 | puts "#ifndef __#{ARGV[0].upcase}_PIE_FIELD_DECODER_H__" 79 | puts "#define __#{ARGV[0].upcase}_PIE_FIELD_DECODER_H__" 80 | puts "#include " 81 | 82 | generate_field_decoder(insts, inst_len, true, false) 83 | 84 | puts "#endif" 85 | end 86 | 87 | def generate_all(insts, inst_len, swaphw) 88 | puts "#include \"pie-#{ARGV[0]}-field-decoder.h\"" 89 | 90 | generate_field_decoder(insts, inst_len, false, swaphw) 91 | end 92 | 93 | is_header = ARGV[1...ARGV.size].include?("header") 94 | swaphw = ARGV[1...ARGV.size].include?("swaphw") 95 | 96 | insts = process_all(ARGV[0] + ".txt", false) 97 | inst_len = get_min_inst_len(insts) 98 | if (is_header) 99 | generate_header(insts, inst_len) 100 | else 101 | generate_all(insts, inst_len, swaphw) 102 | end 103 | -------------------------------------------------------------------------------- /pie/makefile: -------------------------------------------------------------------------------- 1 | CFLAGS= -Os -Wall -g -std=c99 #-DPIE_AUTOINC 2 | 3 | C_ARCH = $(shell $(CC) -dumpmachine | awk -F '-' '{print $$1}') 4 | ifeq ($(findstring arm, $(C_ARCH)), arm) 5 | NATIVE_TARGETS = arm thumb 6 | endif 7 | ifeq ($(C_ARCH),aarch64) 8 | NATIVE_TARGETS = a64 9 | endif 10 | ifeq ($(C_ARCH),riscv64) 11 | NATIVE_TARGETS = riscv 12 | endif 13 | 14 | ifeq ($(ARCH),riscv) 15 | OPTS=swaphw 16 | endif 17 | 18 | .SECONDARY: 19 | .PHONY: native print_arch all pie clean 20 | 21 | native: print_arch $(NATIVE_TARGETS) 22 | 23 | print_arch: 24 | $(info PIE: detected architecture "$(C_ARCH)") 25 | 26 | all: thumb arm a64 riscv 27 | 28 | %: 29 | $(MAKE) --no-print-directory ARCH=$@ pie 30 | 31 | pie: pie-$(ARCH)-decoder.o pie-$(ARCH)-encoder.o pie-$(ARCH)-field-decoder.o 32 | 33 | pie-$(ARCH)-%.o: pie-$(ARCH)-%.c pie-$(ARCH)-%.h 34 | $(CC) -c $(CFLAGS) $< -o $@ 35 | 36 | pie-$(ARCH)-%.h: generate_%.rb $(ARCH).txt 37 | ruby $< $(ARCH) header $(OPTS) > $@ 38 | 39 | pie-$(ARCH)-%.c: generate_%.rb $(ARCH).txt 40 | ruby $< $(ARCH) $(OPTS) > $@ 41 | 42 | clean: 43 | rm -f *.o pie-arm-*.h pie-thumb-*.h pie-a64-*.h pie-riscv-*.h pie-*.c 44 | 45 | -------------------------------------------------------------------------------- /plugins.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of MAMBO, a low-overhead dynamic binary modification tool: 3 | https://github.com/beehive-lab/mambo 4 | 5 | Copyright 2013-2016 Cosmin Gorgovan 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | #include "dbm.h" 21 | #include "scanner_public.h" 22 | #ifdef __arm__ 23 | #include "api/emit_thumb.h" 24 | #include "api/emit_arm.h" 25 | #include "pie/pie-arm-field-decoder.h" 26 | #include "pie/pie-arm-decoder.h" 27 | #include "pie/pie-thumb-field-decoder.h" 28 | #include "pie/pie-thumb-decoder.h" 29 | #elif __aarch64__ 30 | #include "api/emit_a64.h" 31 | #include "pie/pie-a64-field-decoder.h" 32 | #include "pie/pie-a64-decoder.h" 33 | #elif __riscv 34 | #include "api/emit_riscv.h" 35 | #include "pie/pie-riscv-field-decoder.h" 36 | #include "pie/pie-riscv-decoder.h" 37 | #endif 38 | #include "api/helpers.h" 39 | #include "scanner_common.h" 40 | #include "api/hash_table.h" 41 | -------------------------------------------------------------------------------- /plugins/branch_count.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of MAMBO, a low-overhead dynamic binary modification tool: 3 | https://github.com/beehive-lab/mambo 4 | 5 | Copyright 2013-2016 Cosmin Gorgovan 6 | Copyright 2017 The University of Manchester 7 | 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | */ 20 | 21 | #ifdef PLUGINS_NEW 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include "../plugins.h" 28 | 29 | struct br_count { 30 | uint64_t direct_branch_count; 31 | uint64_t indirect_branch_count; 32 | uint64_t return_branch_count; 33 | }; 34 | 35 | struct br_count global_counters; 36 | 37 | int branch_count_pre_thread_handler(mambo_context *ctx) { 38 | struct br_count *counters = mambo_alloc(ctx, sizeof(struct br_count)); 39 | assert(counters != NULL); 40 | mambo_set_thread_plugin_data(ctx, counters); 41 | 42 | counters->direct_branch_count = 0; 43 | counters->indirect_branch_count = 0; 44 | counters->return_branch_count = 0; 45 | } 46 | 47 | void print_counters(struct br_count *counters) { 48 | fprintf(stderr, " direct branches: %'" PRIu64 "\n", counters->direct_branch_count); 49 | fprintf(stderr, " indirect branches: %'" PRIu64 "\n", counters->indirect_branch_count); 50 | fprintf(stderr, " returns: %'" PRIu64 "\n", counters->return_branch_count); 51 | } 52 | 53 | int branch_count_post_thread_handler(mambo_context *ctx) { 54 | struct br_count *counters = mambo_get_thread_plugin_data(ctx); 55 | 56 | fprintf(stderr, "Thread: %d\n", mambo_get_thread_id(ctx)); 57 | print_counters(counters); 58 | atomic_increment_u64(&global_counters.direct_branch_count, 59 | counters->direct_branch_count); 60 | atomic_increment_u64(&global_counters.indirect_branch_count, 61 | counters->indirect_branch_count); 62 | atomic_increment_u64(&global_counters.return_branch_count, 63 | counters->return_branch_count); 64 | mambo_free(ctx, counters); 65 | } 66 | 67 | int branch_count_exit_handler(mambo_context *ctx) { 68 | fprintf(stderr, "Total:\n"); 69 | print_counters(&global_counters); 70 | } 71 | 72 | int branch_count_pre_inst_handler(mambo_context *ctx) { 73 | struct br_count *counters = mambo_get_thread_plugin_data(ctx); 74 | uint64_t *counter = NULL; 75 | 76 | mambo_branch_type type = mambo_get_branch_type(ctx); 77 | if (type & BRANCH_RETURN) { 78 | counter = &counters->return_branch_count; 79 | } else if (type & BRANCH_DIRECT) { 80 | counter = &counters->direct_branch_count; 81 | } else if (type & BRANCH_INDIRECT) { 82 | counter = &counters->indirect_branch_count; 83 | } 84 | 85 | if (counter != NULL) { 86 | emit_counter64_incr(ctx, counter, 1); 87 | } 88 | } 89 | 90 | __attribute__((constructor)) void branch_count_init_plugin() { 91 | mambo_context *ctx = mambo_register_plugin(); 92 | assert(ctx != NULL); 93 | 94 | mambo_register_pre_inst_cb(ctx, &branch_count_pre_inst_handler); 95 | mambo_register_pre_thread_cb(ctx, &branch_count_pre_thread_handler); 96 | mambo_register_post_thread_cb(ctx, &branch_count_post_thread_handler); 97 | mambo_register_exit_cb(ctx, &branch_count_exit_handler); 98 | 99 | setlocale(LC_NUMERIC, ""); 100 | } 101 | #endif 102 | -------------------------------------------------------------------------------- /plugins/cachesim/cachesim.S: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of MAMBO, a low-overhead dynamic binary modification tool: 3 | https://github.com/beehive-lab/mambo 4 | 5 | Copyright 2017 The University of Manchester 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | #include "cachesim_buffer.h" 21 | 22 | #ifdef __arm__ 23 | .syntax unified 24 | #endif 25 | 26 | .global cachesim_buf_write // (value, info, &buf_ptr.entries[0]) 27 | .func 28 | .type mtrace_buf_write, %function 29 | 30 | #ifdef __arm__ 31 | .thumb_func 32 | cachesim_buf_write: 33 | PUSH {R3, R4} 34 | LDR R3, [R2, #-4] 35 | ADD R4, R2, R3, LSL #3 36 | STRD R0, R1, [R4] 37 | ADD R3, R3, #1 38 | STR R3, [R2, #-4] 39 | SUB R3, R3, #BUFLEN 40 | CBZ R3, call 41 | POP {R3, R4} 42 | BX LR 43 | 44 | call: 45 | PUSH {R0-R2, R5-R6, R9, R12, LR} 46 | VPUSH {D16-D31} 47 | VPUSH {D0-D7} 48 | MRS R4, CPSR 49 | VMRS R5, FPSCR 50 | 51 | SUB R0, R2, #4 52 | 53 | MOV R6, SP 54 | BIC R2, R6, #7 55 | MOV SP, R2 56 | LDR R1, =cachesim_proc_buf 57 | BLX R1 58 | MOV SP, R6 59 | 60 | MSR CPSR, R4 61 | VMSR FPSCR, R5 62 | VPOP {D0-D7} 63 | VPOP {D16-D31} 64 | POP {R0-R2, R5-R6, R9, R12, LR} 65 | POP {R3 - R4} 66 | BX LR 67 | #endif 68 | 69 | #ifdef __aarch64__ 70 | cachesim_buf_write: 71 | STP X3, X4, [SP, #-16]! 72 | LDR W3, [X2, #-8] 73 | ADD X4, X2, W3, UXTW #4 74 | STP X0, X1, [X4] 75 | 76 | ADD W3, W3, #1 77 | STR W3, [X2, #-8] 78 | SUB W3, W3, #BUFLEN 79 | CBZ W3, call 80 | LDP X3, X4, [SP], #16 81 | RET 82 | 83 | call: 84 | STP X29, X30, [SP, #-16]! 85 | 86 | BL push_x4_x21 87 | MRS X19, NZCV 88 | MRS X20, FPCR 89 | MRS X21, FPSR 90 | BL push_neon 91 | 92 | SUB X0, X2, #8 93 | LDR X1, =cachesim_proc_buf 94 | BLR X1 95 | 96 | BL pop_neon 97 | MSR NZCV, X19 98 | MSR FPCR, X20 99 | MSR FPSR, X21 100 | BL pop_x4_x21 101 | 102 | LDP X3, X4, [SP, #16] 103 | LDP X29, X30, [SP], #32 104 | RET 105 | #endif 106 | 107 | .endfunc 108 | -------------------------------------------------------------------------------- /plugins/cachesim/cachesim_buffer.h: -------------------------------------------------------------------------------- 1 | #define BUFLEN 256 2 | -------------------------------------------------------------------------------- /plugins/cachesim/cachesim_model.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of MAMBO, a low-overhead dynamic binary modification tool: 3 | https://github.com/beehive-lab/mambo 4 | 5 | Copyright 2017 The University of Manchester 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | #include 21 | #include 22 | 23 | 24 | typedef uintptr_t addr_t; 25 | 26 | typedef enum { 27 | REPLACE_RANDOM, 28 | REPLACE_LRU, 29 | } cachesim_policy; 30 | 31 | typedef struct { 32 | addr_t tag; 33 | uint64_t timestamp; 34 | } cachesim_model_line_t; 35 | 36 | typedef struct { 37 | uint64_t references[2]; 38 | uint64_t misses[2]; 39 | uint64_t writebacks[2]; 40 | } cachesim_stats_t; 41 | 42 | typedef struct cachesim_model cachesim_model_t; 43 | #define CACHESIM_NAME_LEN 20 44 | struct cachesim_model { 45 | char name[CACHESIM_NAME_LEN]; 46 | unsigned size; 47 | unsigned line_size; 48 | unsigned max_fetch; 49 | unsigned assoc; 50 | cachesim_policy replacement_policy; 51 | 52 | unsigned sets; 53 | unsigned set_shift; 54 | unsigned set_mask; 55 | unsigned tag_shift; 56 | unsigned max_fetch_shift; 57 | 58 | addr_t last_addr; 59 | int last_line; 60 | 61 | pthread_mutex_t mutex; 62 | 63 | cachesim_model_t *parent; 64 | cachesim_stats_t stats; 65 | cachesim_model_line_t *lines; 66 | }; 67 | 68 | int cachesim_model_init(cachesim_model_t *cache, char *name, unsigned size, 69 | unsigned line_size, unsigned max_fetch, unsigned assoc, 70 | cachesim_policy repl_policy); 71 | void cachesim_model_free(cachesim_model_t *cache); 72 | int cachesim_ref(cachesim_model_t *cache, addr_t addr, unsigned size, bool is_write); 73 | void cachesim_print_stats(cachesim_model_t *cache); 74 | -------------------------------------------------------------------------------- /plugins/datarace/README.md: -------------------------------------------------------------------------------- 1 | MAMBO datarace 2 | ============== 3 | 4 | This instrumentation plugin for [MAMBO](https://github.com/beehive-lab/mambo) detects possible data races with relatively low performance overhead for programs that utilise POSIX pthreads. This is still experimental software, please report any bugs using GitHub's [issue tracker](https://github.com/beehive-lab/mambo/issues). Any improvements and fixes are also welcome with a [pull request.](https://github.com/beehive-lab/mambo/pulls) 5 | 6 | 7 | Building 8 | --------- 9 | 10 | git clone https://github.com/beehive-lab/mambo.git 11 | cd mambo 12 | make datarace_ft 13 | 14 | Usage 15 | ------ 16 | 17 | 18 | To run an application under MAMBO datarace, simply prefix the command with a call to `mambo_datarace_ft`. For example to execute `lscpu`, from the mambo source directory run: 19 | 20 | ./mambo_datarace_ft /usr/bin/lscpu 21 | 22 | > **Note:** Underlying programs must be compiled with the `-no-pie` flag (can be linked statically or dynamically) OR must be dynamically linked with library at /usr/ and mambo compiled with `NO_PIE_ENABLE` disabled in [datarace.h](datarace.h). See limitations at the bottom for more information. 23 | 24 | 25 | Configuration 26 | ------------- 27 | 28 | #### FastTrack and Djit+ 29 | 30 | There are two separate algorithms to choose from for the datarace detector: [FastTrack](https://dl.acm.org/doi/abs/10.1145/1543135.1542490) and [DJIT+](https://dl.acm.org/doi/abs/10.1145/781498.781529). Both algorithms utilise the happens-before relationship. FastTrack is known to be an improvement over DJIT+ implementations by carrying out a happens-before comparison in O(1) for the majority of the cases compared to DJIT+'s O(n). 31 | 32 | > To compile and use the DJIT+ implementation, use `make datarace_djit` and run with `./mambo_datarace_djit`. 33 | 34 | #### Further configuration 35 | 36 | Further algorithms can be implemented using the handling functions for the various thread operations at the beginning of [datarace.c](datarace.c). Details of the implementation are also included at the top of the file for easier modification. 37 | 38 | [datarace.h](datarace.h) contains an option `no-pie` option enabled by default, to properly ignore libc. More debug information can also be enabled. 39 | 40 | Limitations 41 | ------------ 42 | 43 | The number of supported threads must be specified with `VC_INITIAL_SZ` in [detector.h](./detectors/detector.h) before compilation. It would be better to set this value to something like 4 or 8, and have it dynamically grow. This will require handling VC clocks of various sizes. Some work has been done for this feature in [fasttrack.c](./detectors/fasttrack.c) and commented out as a TODO to complete. 44 | 45 | Currently libc is ignored by not processing any reads/writes to addresses above `0x7000000000` which require the underlying program to be compiled with `no-pie`. A workaround involves dynamically linking to libc and not processing code within the /usr/ directory for data races. There is likely a better solution to this however. Please don't hesitate to open a [pull request](https://github.com/beehive-lab/mambo/pulls) for a fix or any other improvement. -------------------------------------------------------------------------------- /plugins/datarace/datarace.h: -------------------------------------------------------------------------------- 1 | #ifndef DATARACE_H 2 | #define DATARACE_H 3 | 4 | #include "detectors/detector.h" 5 | 6 | #include 7 | #include 8 | 9 | #if !defined(FASTTRACK) && !defined(DJIT) 10 | #error "Neither DJIT nor FASTTRACK is defined" 11 | #endif 12 | 13 | 14 | /* 15 | Define this if exe run under mambo is compiled with -no-pie. (Recommended) 16 | Otherwise exe must be dynamically linked with libs at /usr/. 17 | Required to ignore data race detection in libc. 18 | */ 19 | #define NO_PIE_ENABLE 20 | 21 | /* 22 | Enable for more verbose information. (Recommended) 23 | Prints fork, join, lock, unlock operations for easier debugging of races. 24 | */ 25 | #define INFO 26 | #ifdef INFO 27 | #define info(...) fprintf(stderr, __VA_ARGS__) 28 | #else 29 | #define info(...) 30 | #endif 31 | 32 | #ifdef DEBUG 33 | #define debug(...) fprintf(stderr, __VA_ARGS__) 34 | #else 35 | #define debug(...) 36 | #endif 37 | 38 | typedef struct thread_data { 39 | pthread_mutex_t *mutex; 40 | uint64_t joining_tid; // tid associated with pthread_t in pre join 41 | } thread_data_t; 42 | 43 | #endif // DATARACE_H 44 | -------------------------------------------------------------------------------- /plugins/datarace/detectors/detector.h: -------------------------------------------------------------------------------- 1 | #ifndef DETECTOR_H 2 | #define DETECTOR_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include "../../../api/hash_table.h" 8 | 9 | // Currently support up to VC_INITIAL_SZ threads 10 | #define VC_INITIAL_SZ 8 11 | 12 | // TODO: Add destructors/free functions 13 | 14 | // VECTOR CLOCK // 15 | typedef struct { 16 | int *clocks; 17 | size_t size; 18 | pthread_mutex_t lock; 19 | } vector_clock_t; 20 | 21 | // EPOCH // 22 | #ifdef FASTTRACK 23 | typedef struct { 24 | int clock; 25 | int thread_idx; 26 | pthread_mutex_t lock; 27 | } epoch_t; 28 | #endif // EPOCH 29 | 30 | int vector_clock_init(vector_clock_t *vc, size_t size); 31 | int vector_clock_get(vector_clock_t *vc, int idx); 32 | void vector_clock_increment(vector_clock_t *vc, int idx); 33 | void vector_clock_set(vector_clock_t *vc, int idx, int clock); 34 | int vector_clock_update(vector_clock_t *vc, vector_clock_t *other_vc); 35 | int vector_clock_happens_before(vector_clock_t *vc, vector_clock_t *other_vc); 36 | 37 | 38 | // THREAD // 39 | typedef struct { 40 | size_t idx; 41 | vector_clock_t *vc; 42 | } thread_t; 43 | 44 | int thread_init(thread_t *t, int thread_idx); 45 | int thread_get_clock(thread_t *t); 46 | int thread_get_idx(thread_t *t); 47 | void thread_increment(thread_t *t); 48 | void thread_update_vc(thread_t *t, vector_clock_t *other_clock); 49 | void thread_fork(thread_t *parent_thread, thread_t *child_thread); 50 | void thread_join(thread_t *parent_thread, thread_t *child_thread); 51 | 52 | 53 | // LOCK // 54 | typedef struct { 55 | vector_clock_t *vc; 56 | } lock_t; 57 | 58 | int lock_init(lock_t *l); 59 | void lock_acquire(lock_t *lock, thread_t *thread); 60 | void lock_release(lock_t *lock, thread_t *thread); 61 | 62 | 63 | // VARIABLE // 64 | #if defined(FASTTRACK) 65 | typedef struct { 66 | vector_clock_t *rx_vc; 67 | epoch_t *rx_epoch; 68 | epoch_t *wx_epoch; 69 | bool is_shared; 70 | } variable_t; 71 | 72 | #elif defined(DJIT) 73 | typedef struct { 74 | vector_clock_t *rx; 75 | vector_clock_t *wx; 76 | } variable_t; 77 | 78 | #endif // VARIABLE 79 | 80 | int variable_init(variable_t *v); 81 | int variable_read_is_race_free(variable_t *v, vector_clock_t *thread_clock); 82 | int variable_write_is_race_free(variable_t *v, vector_clock_t *thread_clock); 83 | int variable_update_read(variable_t *v, thread_t *thread); 84 | int variable_update_write(variable_t *v, thread_t *thread); 85 | 86 | 87 | // Lists 88 | // ThreadList 89 | typedef struct { 90 | thread_t **threads; // array of threads 91 | size_t size; 92 | size_t capacity; 93 | mambo_ht_t *tid_index_ht; // tid -> index ht 94 | pthread_mutex_t lock; 95 | } thread_list_t; 96 | 97 | typedef struct { 98 | lock_t **locks; 99 | size_t size; 100 | size_t capacity; 101 | mambo_ht_t *addr_index_ht; // address -> index ht 102 | pthread_mutex_t lock; 103 | } lock_list_t; 104 | 105 | typedef struct { 106 | variable_t **variables; 107 | size_t size; 108 | size_t capacity; 109 | mambo_ht_t *addr_index_ht; // address -> index ht 110 | pthread_mutex_t lock; 111 | } variable_list_t; 112 | 113 | // smart_get: return if item in list, else adds it and returns it 114 | 115 | int thread_list_init(thread_list_t *list); 116 | thread_t *thread_list_append(thread_list_t *list, uint64_t tid); 117 | thread_t *thread_list_smart_get(thread_list_t *list, uint64_t tid); 118 | 119 | int lock_list_init(lock_list_t *list); 120 | lock_t *lock_list_append(lock_list_t *list, uintptr_t addr); 121 | lock_t *lock_list_smart_get(lock_list_t *list, uintptr_t addr); 122 | 123 | int variable_list_init(variable_list_t *list); 124 | variable_t *variable_list_append(variable_list_t *list, uintptr_t addr); 125 | variable_t *variable_list_smart_get(variable_list_t *list, uintptr_t addr); 126 | 127 | 128 | #endif // DETECTOR_H 129 | -------------------------------------------------------------------------------- /plugins/follow_exec.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of MAMBO, a low-overhead dynamic binary modification tool: 3 | https://github.com/beehive-lab/mambo 4 | 5 | Copyright 2021 The University of Manchester 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | /* 21 | This plugin will make MAMBO 'follow' into any new process started by the 22 | application under its control by prepending a call to itself on every execve 23 | */ 24 | 25 | #ifdef PLUGINS_NEW 26 | 27 | //#include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #include "../plugins.h" 35 | 36 | char self_exe[NAME_MAX]; 37 | 38 | int count_args(uintptr_t *args) { 39 | // count includes the NULL terminator 40 | int count = 1; 41 | while ((*args) != 0) { 42 | count++; 43 | args++; 44 | } 45 | return count; 46 | } 47 | 48 | int follow_exec_syscall(mambo_context *ctx) { 49 | uintptr_t call_no; 50 | uintptr_t *args; 51 | int ret = mambo_syscall_get_no(ctx, &call_no); 52 | assert(ret == 0); 53 | 54 | if (call_no == __NR_execve) { 55 | mambo_syscall_get_args(ctx, &args); 56 | assert(args != NULL); 57 | 58 | mambo_syscall_bypass(ctx); 59 | 60 | /* 61 | We have to do some error checking here to emulate execve errors. 62 | If we just try to launch a missing or invalid executable with MAMBO, 63 | we'll only encounter an error after the parent has been replaced by 64 | the newly launched MAMBO process, and at that point there's no parent 65 | to return the error to 66 | */ 67 | if (access((char *)args[0], F_OK)) { 68 | mambo_syscall_set_return(ctx, -ENOENT); 69 | return 0; 70 | } 71 | 72 | // copy argv 73 | int arg_count = count_args((uintptr_t *)args[1]); 74 | uintptr_t *tmp_argv = alloca((arg_count+1) * sizeof(uintptr_t)); 75 | memcpy(&tmp_argv[1], (uintptr_t *)args[1], arg_count * sizeof(uintptr_t)); 76 | 77 | // set the original path as the first argument for MAMBO 78 | tmp_argv[1] = args[0]; 79 | // prepend the path of our own executable to MAMBO's argv 80 | tmp_argv[0] = (uintptr_t)self_exe; 81 | 82 | uintptr_t ret = raw_syscall(call_no, self_exe, tmp_argv, args[2]); 83 | /* Normally we shouldn't return here. If we did, it means that 84 | MAMBO failed to start, rather than the application. */ 85 | mambo_syscall_set_return(ctx, ret); 86 | } 87 | 88 | return 0; 89 | } 90 | 91 | __attribute__((constructor)) void follow_exec_init_plugin() { 92 | mambo_context *ctx = mambo_register_plugin(); 93 | assert(ctx != NULL); 94 | 95 | ssize_t ret = readlink("/proc/self/exe", self_exe, NAME_MAX); 96 | assert(ret > 0 && ret < NAME_MAX); 97 | self_exe[ret] = '\0'; 98 | 99 | mambo_register_pre_syscall_cb(ctx, &follow_exec_syscall); 100 | } 101 | #endif 102 | -------------------------------------------------------------------------------- /plugins/memcheck/README.md: -------------------------------------------------------------------------------- 1 | MAMBO memcheck 2 | ============== 3 | 4 | This instrumentation plugin for [MAMBO](https://github.com/beehive-lab/mambo) detects memory usage errors such as out-of-bounds accesses and invalid `free()` calls with relatively low performance overhead. This is still experimental software, please report any problems using [github's issue tracker](https://github.com/beehive-lab/mambo/issues). 5 | 6 | 7 | Publications 8 | ------------ 9 | 10 | * [Cosmin Gorgovan, Guillermo Callaghan, and Mikel Luján. Balancing Performance and Productivity for the Development of Dynamic Binary Instrumentation Tools - A Case Study on Arm Systems. In Proceedings of the 29th International Conference on Compiler Construction (CC ’20)](https://dl.acm.org/doi/abs/10.1145/3377555.3377895) **Free download** [via research.manchester.ac.uk](https://www.research.manchester.ac.uk/portal/en/publications/balancing-performance-and-productivity-for-the-development-of-dynamic-binary-instrumentation-tools--a-case-study-on-arm-systems(80e57c1b-9e38-4a15-942d-eb240888b12b).html). 11 | 12 | 13 | Building 14 | -------- 15 | 16 | git clone --recurse-submodules https://github.com/beehive-lab/mambo.git 17 | cd mambo 18 | make memcheck 19 | 20 | 21 | Usage 22 | ----- 23 | 24 | To run an application under MAMBO memcheck, simply prefix the command with a call to `mambo_memcheck`. For example to execute `lscpu`, from the mambo source directory run: 25 | 26 | ./mambo_memcheck /usr/bin/lscpu 27 | 28 | or 29 | 30 | ./mambo_memcheck `which lscpu` 31 | 32 | When an application runs under MAMBO memcheck, the first output should be its git version, e.g.: 33 | 34 | $ ./mambo_memcheck `which lscpu` 35 | 36 | -- MAMBO memcheck 29f87421 -- 37 | 38 | Architecture: aarch64 39 | CPU op-mode(s): 32-bit, 64-bit 40 | [...] 41 | 42 | Please include the git version in any bug reports. 43 | 44 | You can also copy `mambo_memcheck` somewhere in your `PATH`, for example `/usr/local/bin`. 45 | 46 | 47 | Example output from a buggy application 48 | --------------------------------------- 49 | 50 | $ mambo_memcheck ~/test 51 | 52 | -- MAMBO memcheck 29f87421 -- 53 | 54 | ==memcheck== Invalid store (size 4) to 0x3ffce462c8 55 | ==memcheck== at [main]+0x60 (0x3ffffac978) in /home/cosmin/test 56 | ==memcheck== Backtrace: 57 | ==memcheck== at [__libc_start_main]+0xe4 (0x3ffd06c12c) in /usr/lib/libc-2.30.so 58 | ==memcheck== at [(null)]+0x7e4 (0x3ffffac7e4) in /home/cosmin/test 59 | 60 | ==memcheck== Invalid load (size 4) from 0x3ffce462cc 61 | ==memcheck== at [main]+0x80 (0x3ffffac998) in /home/cosmin/test 62 | ==memcheck== Backtrace: 63 | ==memcheck== at [__libc_start_main]+0xe4 (0x3ffd06c12c) in /usr/lib/libc-2.30.so 64 | ==memcheck== at [(null)]+0x7e4 (0x3ffffac7e4) in /home/cosmin/test 65 | 66 | ==memcheck== double free for 0x3ffce466e0 67 | 68 | 69 | Advanced configuration 70 | ---------------------- 71 | 72 | One of the more challenging aspects of this software is avoiding noisy false positive errors, e.g. harmless out-of-bounds reads in the hand written assembly code from glibc. We have implemented a number of techniques to avoid reporting such errors, which are documented and can be enabled or disabled in [memcheck.h](memcheck.h). 73 | -------------------------------------------------------------------------------- /plugins/memcheck/memcheck.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of MAMBO, a low-overhead dynamic binary modification tool: 3 | https://github.com/beehive-lab/mambo 4 | 5 | Copyright 2017-2020 The University of Manchester 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | #define COMPACT_SHADOW 1 21 | 22 | /* ignore invalid accesses from a whitelist of instructions found in glibc functions 23 | known to perform safe (aligned) out-of-bounds reads for performance optimisation 24 | may lead to false negatives */ 25 | //#define MC_IGNORE_LIST 1 26 | 27 | /* replace the standard library functions known to have glibc implementations that 28 | perform safe (aligned) out-of-bounds reads for performance reasons 29 | the replacement implementations are naive - may affect application performance */ 30 | #define MC_REPLACE_FNS 1 31 | 32 | /* ignore errors in the dynamic loader 33 | some distributions seem to ship stripped linker executables, which means that we 34 | can't hook their embedded stdlib functions, so we'll get some false positive errors 35 | as the dynamic loader sets up 36 | this options will cause memcheck to ignore all invalid accesses in the loader */ 37 | #define MC_IGNORE_INTERP 1 38 | 39 | #ifdef COMPACT_SHADOW 40 | #define SHADOW_SIZE (RESERVED_BASE/8) 41 | #else 42 | #define SHADOW_SIZE (RESERVED_BASE*2) 43 | #ifdef __arm__ 44 | #error Uncompacted shadow memory not supported on AArch32 45 | #endif 46 | #endif 47 | 48 | #define VDSO_SIZE (PAGE_SIZE*2) 49 | #ifdef __aarch64__ 50 | #define RESERVED_BASE 0x4000000000 // 256 GiB 51 | #define RESERVED_TOP (vdso_base - PAGE_SIZE) 52 | #define INITIAL_RES_SIZE (0x1000000000) // 64 GiB 53 | #elif __arm__ 54 | #define RESERVED_BASE 0x80000000 55 | #define INITIAL_RES_SIZE (128*1024*1024) 56 | #endif 57 | 58 | -------------------------------------------------------------------------------- /plugins/mtrace.S: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of MAMBO, a low-overhead dynamic binary modification tool: 3 | https://github.com/beehive-lab/mambo 4 | 5 | Copyright 2017 The University of Manchester 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | #include "mtrace.h" 21 | 22 | #ifdef __arm__ 23 | .syntax unified 24 | #endif 25 | 26 | .global mtrace_buf_write // (value, info, &buf_ptr.entries[0]) 27 | .func 28 | .type mtrace_buf_write, %function 29 | 30 | #ifdef __arm__ 31 | .thumb_func 32 | mtrace_buf_write: 33 | PUSH {R3, R4} 34 | LDR R3, [R2, #-4] 35 | ADD R4, R2, R3, LSL #3 36 | STRD R0, R1, [R4] 37 | ADD R3, R3, #1 38 | STR R3, [R2, #-4] 39 | SUB R3, R3, #BUFLEN 40 | CBZ R3, call 41 | POP {R3, R4} 42 | BX LR 43 | 44 | call: 45 | PUSH {R0-R2, R5-R6, R9, R12, LR} 46 | VPUSH {D16-D31} 47 | VPUSH {D0-D7} 48 | MRS R4, CPSR 49 | VMRS R5, FPSCR 50 | 51 | SUB R0, R2, #4 52 | 53 | MOV R6, SP 54 | BIC R2, R6, #7 55 | MOV SP, R2 56 | LDR R1, =mtrace_print_buf 57 | BLX R1 58 | MOV SP, R6 59 | 60 | MSR CPSR, R4 61 | VMSR FPSCR, R5 62 | VPOP {D0-D7} 63 | VPOP {D16-D31} 64 | POP {R0-R2, R5-R6, R9, R12, LR} 65 | POP {R3 - R4} 66 | BX LR 67 | #endif 68 | 69 | #ifdef __aarch64__ 70 | mtrace_buf_write: 71 | STP X3, X4, [SP, #-16]! 72 | LDR W3, [X2, #-8] 73 | ADD X4, X2, W3, UXTW #4 74 | STP X0, X1, [X4] 75 | 76 | ADD W3, W3, #1 77 | STR W3, [X2, #-8] 78 | SUB W3, W3, #BUFLEN 79 | CBZ W3, call 80 | LDP X3, X4, [SP], #16 81 | RET 82 | 83 | call: 84 | STP X29, X30, [SP, #-16]! 85 | 86 | BL push_x4_x21 87 | MRS X19, NZCV 88 | MRS X20, FPCR 89 | MRS X21, FPSR 90 | BL push_neon 91 | 92 | SUB X0, X2, #8 93 | LDR X1, =mtrace_print_buf 94 | BLR X1 95 | 96 | BL pop_neon 97 | MSR NZCV, X19 98 | MSR FPCR, X20 99 | MSR FPSR, X21 100 | BL pop_x4_x21 101 | 102 | LDP X3, X4, [SP, #16] 103 | LDP X29, X30, [SP], #32 104 | RET 105 | #endif 106 | 107 | .endfunc 108 | -------------------------------------------------------------------------------- /plugins/mtrace.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of MAMBO, a low-overhead dynamic binary modification tool: 3 | https://github.com/beehive-lab/mambo 4 | 5 | Copyright 2017 The University of Manchester 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | #ifdef PLUGINS_NEW 21 | 22 | #include 23 | #include 24 | #include 25 | #include "../plugins.h" 26 | 27 | #include "mtrace.h" 28 | 29 | struct mtrace_entry { 30 | uintptr_t addr; 31 | uintptr_t info; 32 | }; 33 | 34 | struct mtrace { 35 | uint32_t len; 36 | struct mtrace_entry entries[BUFLEN]; 37 | }; 38 | 39 | extern void mtrace_print_buf_trampoline(struct mtrace *trace); 40 | extern void mtrace_buf_write(uintptr_t value, struct mtrace *trace); 41 | 42 | void mtrace_print_buf(struct mtrace *mtrace_buf) { 43 | for (int i = 0; i < mtrace_buf->len; i++) { 44 | /* Warning: printing formatted strings is very slow 45 | For practical use, you are encouraged to process the data in memory 46 | or write the trace in the raw binary format */ 47 | int size = (int)(mtrace_buf->entries[i].info >> 1); 48 | char *type = (mtrace_buf->entries[i].info & 1) ? "w" : "r"; 49 | fprintf(stderr, "%s: %p\t%d\n", type, (void *)mtrace_buf->entries[i].addr, size); 50 | } 51 | mtrace_buf->len = 0; 52 | } 53 | 54 | int mtrace_pre_inst_handler(mambo_context *ctx) { 55 | struct mtrace *mtrace_buf = mambo_get_thread_plugin_data(ctx); 56 | bool is_load = mambo_is_load(ctx); 57 | bool is_store = mambo_is_store(ctx); 58 | if (is_load || is_store) { 59 | mambo_cond cond = mambo_get_cond(ctx); 60 | mambo_branch skip_br; 61 | int ret; 62 | if (cond != AL) { 63 | ret = mambo_reserve_branch(ctx, &skip_br); 64 | assert(ret == 0); 65 | } 66 | 67 | emit_push(ctx, (1 << 0) | (1 << 1) | (1 << 2) | (1 << lr)); 68 | 69 | ret = mambo_calc_ld_st_addr(ctx, 0); 70 | assert(ret == 0); 71 | int size = mambo_get_ld_st_size(ctx); 72 | assert(size > 0); 73 | 74 | uintptr_t info = (size << 1) | (is_store ? 1 : 0); 75 | emit_set_reg(ctx, 1, info); 76 | emit_set_reg_ptr(ctx, 2, &mtrace_buf->entries); 77 | emit_fcall(ctx, mtrace_buf_write); 78 | 79 | emit_pop(ctx, (1 << 0) | (1 << 1) | (1 << 2) | (1 << lr)); 80 | 81 | if (cond != AL) { 82 | ret = emit_local_branch_cond(ctx, &skip_br, invert_cond(cond)); 83 | assert(ret == 0); 84 | } 85 | } 86 | } 87 | 88 | int mtrace_pre_thread_handler(mambo_context *ctx) { 89 | struct mtrace *mtrace_buf = mambo_alloc(ctx, sizeof(*mtrace_buf)); 90 | assert(mtrace_buf != NULL); 91 | mtrace_buf->len = 0; 92 | 93 | int ret = mambo_set_thread_plugin_data(ctx, mtrace_buf); 94 | assert(ret == MAMBO_SUCCESS); 95 | } 96 | 97 | int mtrace_post_thread_handler(mambo_context *ctx) { 98 | struct mtrace *mtrace_buf = mambo_get_thread_plugin_data(ctx); 99 | mtrace_print_buf(mtrace_buf); 100 | mambo_free(ctx, mtrace_buf); 101 | } 102 | 103 | __attribute__((constructor)) void mtrace_init_plugin() { 104 | mambo_context *ctx = mambo_register_plugin(); 105 | assert(ctx != NULL); 106 | 107 | mambo_register_pre_thread_cb(ctx, &mtrace_pre_thread_handler); 108 | mambo_register_post_thread_cb(ctx, &mtrace_post_thread_handler); 109 | mambo_register_pre_inst_cb(ctx, &mtrace_pre_inst_handler); 110 | } 111 | #endif 112 | -------------------------------------------------------------------------------- /plugins/mtrace.h: -------------------------------------------------------------------------------- 1 | #define BUFLEN 2047 2 | -------------------------------------------------------------------------------- /plugins/poc_log_returns.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of MAMBO, a low-overhead dynamic binary modification tool: 3 | https://github.com/beehive-lab/mambo 4 | 5 | Copyright 2018 The University of Manchester 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | #ifdef PLUGINS_NEW 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include "../plugins.h" 27 | 28 | void log_returns_print(void *return_from, void *return_to) { 29 | fprintf(stderr, "Return from %p to %p\n", return_from, return_to); 30 | } 31 | 32 | /* Proof of concept. Note that only a subset of returns are currently instrumented by this code */ 33 | int log_returns_pre_inst(mambo_context *ctx) { 34 | bool instrument = false; 35 | int inst = mambo_get_inst(ctx); 36 | #ifdef __arm__ 37 | inst_set isa = mambo_get_inst_type(ctx); 38 | if (isa == ARM_INST) { 39 | if (inst == ARM_BX) { 40 | uint32_t rn; 41 | arm_bx_decode_fields(mambo_get_source_addr(ctx), &rn); 42 | if (rn == lr) { 43 | instrument = true; 44 | } 45 | } 46 | } else if (isa == THUMB_INST) { 47 | fprintf(stderr, "poc_log_returns: Thumb support not implemented yet\n"); 48 | } 49 | #elif __riscv 50 | if (inst == RISCV_JALR) { 51 | unsigned int rd; 52 | unsigned int rs1; 53 | unsigned int imm; 54 | riscv_jalr_decode_fields(mambo_get_source_addr(ctx), &rd, &rs1, &imm); 55 | if (rd == x0 && rs1 == x1) { 56 | instrument = true; 57 | } 58 | } else if (inst == RISCV_C_JR) { 59 | unsigned int rs1; 60 | riscv_c_jalr_decode_fields(mambo_get_source_addr(ctx), &rs1); 61 | if (rs1 == x1) { 62 | instrument = true; 63 | } 64 | } 65 | #else 66 | #error "Current ISA not supported yet" 67 | #endif 68 | if (instrument) { 69 | emit_push(ctx, (1 << reg0) | (1 << reg1)); 70 | emit_set_reg_ptr(ctx, reg0, mambo_get_source_addr(ctx)); 71 | emit_mov(ctx, reg1, lr); 72 | emit_safe_fcall(ctx, log_returns_print, 2); 73 | emit_pop(ctx, (1 << reg0) | (1 << reg1)); 74 | } 75 | } 76 | 77 | __attribute__((constructor)) void branch_count_init_plugin() { 78 | mambo_context *ctx = mambo_register_plugin(); 79 | assert(ctx != NULL); 80 | 81 | mambo_register_pre_inst_cb(ctx, &log_returns_pre_inst); 82 | } 83 | #endif 84 | -------------------------------------------------------------------------------- /plugins/strace.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of MAMBO, a low-overhead dynamic binary modification tool: 3 | https://github.com/beehive-lab/mambo 4 | 5 | Copyright 2019 University of Manchester 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | #ifdef PLUGINS_NEW 21 | #include 22 | #include 23 | #include 24 | #include "../plugins.h" 25 | 26 | #define DEBUG 27 | 28 | #ifdef DEBUG 29 | #define debug(...) fprintf(stderr, __VA_ARGS__) 30 | #else 31 | #define debug(...) 32 | #endif 33 | 34 | int strace_pre(mambo_context *ctx) { 35 | uintptr_t call_no; 36 | uintptr_t *args; 37 | int ret = mambo_syscall_get_no(ctx, &call_no); 38 | assert(ret == 0); 39 | mambo_syscall_get_args(ctx, &args); 40 | assert(args != NULL); 41 | fprintf(stderr, "syscall(%"PRIuPTR", 0x%"PRIxPTR", 0x%"PRIxPTR", 0x%"PRIxPTR", 0x%"PRIxPTR", [...])", call_no, args[0], args[1], args[2], args[3]); 42 | } 43 | 44 | int strace_post(mambo_context *ctx) { 45 | uintptr_t syscall_ret; 46 | int ret = mambo_syscall_get_return(ctx, &syscall_ret); 47 | assert(ret == 0); 48 | fprintf(stderr, " = 0x%"PRIxPTR"\n", syscall_ret); 49 | } 50 | 51 | __attribute__((constructor)) void init_strace() { 52 | mambo_context *ctx = mambo_register_plugin(); 53 | assert(ctx != NULL); 54 | mambo_register_pre_syscall_cb(ctx, &strace_pre); 55 | mambo_register_post_syscall_cb(ctx, &strace_post); 56 | } 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /plugins/symbol_example.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of MAMBO, a low-overhead dynamic binary modification tool: 3 | https://github.com/beehive-lab/mambo 4 | 5 | Copyright 2019-2020 The University of Manchester 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include "../plugins.h" 30 | 31 | void se_print(size_t size, uintptr_t at, uintptr_t caller) { 32 | char *at_name = NULL; 33 | char *caller_name = NULL; 34 | 35 | get_symbol_info_by_addr(at, &at_name, NULL, NULL); 36 | get_symbol_info_by_addr(caller, &caller_name, NULL, NULL); 37 | 38 | printf("malloc(%zu) at %" PRIxPTR "(%s)\n", size, at, at_name); 39 | printf(" called from %" PRIxPTR "(%s)\n", caller, caller_name); 40 | } 41 | 42 | int se_hook(mambo_context *ctx) { 43 | emit_push(ctx, (1 << reg0) | (1 << reg1) | (1 << reg2)); 44 | emit_set_reg_ptr(ctx, reg1, mambo_get_source_addr(ctx)); 45 | emit_mov(ctx, reg2, lr); 46 | emit_safe_fcall(ctx, se_print, 3); 47 | emit_pop(ctx, (1 << reg0) | (1 << reg1) | (1 << reg2)); 48 | return 0; 49 | } 50 | 51 | __attribute__((constructor)) void memcheck_init_plugin() { 52 | mambo_context *ctx = mambo_register_plugin(); 53 | assert(ctx != NULL); 54 | 55 | int ret = mambo_register_function_cb(ctx, "malloc", &se_hook, NULL, 1); 56 | assert(ret == MAMBO_SUCCESS); 57 | } 58 | -------------------------------------------------------------------------------- /plugins/tb_count.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of MAMBO, a low-overhead dynamic binary modification tool: 3 | https://github.com/beehive-lab/mambo 4 | 5 | Copyright 2013-2016 Cosmin Gorgovan 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | #ifdef PLUGINS_NEW 21 | #ifdef __arm__ 22 | 23 | #include 24 | #include 25 | #include 26 | #include "../plugins.h" 27 | 28 | // Called for each instruction scanned by MAMBO, before the translation is generated 29 | int tb_cnt_pre_inst_handler(mambo_context *ctx) { 30 | void *skip_branch = NULL; 31 | 32 | if (mambo_get_inst_type(ctx) == THUMB_INST 33 | && (mambo_get_inst(ctx) == THUMB_TBB32) || (mambo_get_inst(ctx) == THUMB_TBH32)) { 34 | 35 | if (mambo_is_cond(ctx)) { 36 | skip_branch = mambo_get_cc_addr(ctx); 37 | mambo_set_cc_addr(ctx, skip_branch + 2); 38 | } 39 | 40 | emit_thumb_push16(ctx, (1 << r0) | (1 << r1) | (1 << r2)); // PUSH {R0-R2} 41 | emit_thumb_push_cpsr(ctx, r0); // MRS R0, CPSR; PUSH {R0} 42 | // MOVW R0, #(ptr_to_ctr & 0xFFFF) 43 | // MOVT R0, #(ptr_to_ctr >> 16) 44 | emit_thumb_copy_to_reg_32bit(ctx, r0, (uint32_t)mambo_get_thread_plugin_data(ctx)); 45 | emit_thumb_ldrd32(ctx, 1, 1, 0, r0, r1, r2, 0); // LDRD R1, R2, [R0, #0] 46 | emit_thumb_addi16(ctx, 1, r1, r1); // ADDS R1, R1, #1 47 | emit_thumb_adci32(ctx, 0, 0, r2, 0, r2, 0); // ADC R2, R2, #0 48 | emit_thumb_strd32(ctx, 1, 1, 0, r0, r1, r2, 0); // STRD R1, R2, [R0, #0] 49 | emit_thumb_pop_cpsr(ctx, r0); // POP {R0}; MSR CPSR, R0 50 | emit_thumb_pop16(ctx, (1 << r0) | (1 << r1) | (1 << r2)); // POP {R0-R2} 51 | 52 | if (skip_branch != NULL) { 53 | emit_thumb_b16_cond(skip_branch, mambo_get_cc_addr(ctx), mambo_get_cond(ctx)); 54 | fprintf(stderr, "TB count: cond TB instrumentation is untested.\n"); 55 | while(1); 56 | } 57 | } 58 | return 0; 59 | } 60 | 61 | // Called when a new thread is created, including the initial thread 62 | int tb_cnt_pre_thread_handler(mambo_context *ctx) { 63 | uint64_t *inst_counter = mambo_alloc(ctx, sizeof(uint64_t)); 64 | *inst_counter = 0; 65 | assert(inst_counter != NULL); 66 | mambo_set_thread_plugin_data(ctx, inst_counter); 67 | return 0; 68 | } 69 | 70 | // Called when a thread exits, or in all threads when the process exits 71 | int tb_cnt_post_thread_handler(mambo_context *ctx) { 72 | uint64_t *inst_counter = mambo_get_thread_plugin_data(ctx); 73 | fprintf(stderr, "%'llu TB instructions executed in thread %d\n", *inst_counter, mambo_get_thread_id(ctx)); 74 | mambo_free(ctx, inst_counter); 75 | return 0; 76 | } 77 | 78 | __attribute__((constructor)) void tb_init_plugin() { 79 | mambo_context *ctx = mambo_register_plugin(); 80 | assert(ctx != NULL); 81 | 82 | mambo_register_pre_inst_cb(ctx, &tb_cnt_pre_inst_handler); 83 | mambo_register_pre_thread_cb(ctx, &tb_cnt_pre_thread_handler); 84 | mambo_register_post_thread_cb(ctx, &tb_cnt_post_thread_handler); 85 | 86 | setlocale(LC_NUMERIC, ""); 87 | } 88 | 89 | #else // __arm__ 90 | #error The tb_count plugin is only available for AArch32 because the table branch instructions are only available on this architecture 91 | #endif 92 | #endif 93 | -------------------------------------------------------------------------------- /syscalls.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of MAMBO, a low-overhead dynamic binary modification tool: 3 | https://github.com/beehive-lab/mambo 4 | 5 | Copyright 2017-2020 The University of Manchester 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | /* Defined as a multiple of (i.e. 4 bytes on AArch32 21 | and 8 bytes on AArch64), not bytes 22 | */ 23 | #ifdef __arm__ 24 | /* SP decremented twice + 25 | 14 regs pushed by the SVC translation 26 | */ 27 | #define SYSCALL_WRAPPER_STACK_OFFSET (2 + 14) 28 | #define SYSCALL_WRAPPER_FRAME_SIZE (SYSCALL_WRAPPER_STACK_OFFSET) 29 | #elif __aarch64__ 30 | /* 2 regs(x29, x30) pushed by the SVC translation 31 | 2 (TPC, SVC) + 32 | 22 (X0-X21) + 33 | (32*2) NEON/FP registers saved in the wrapper 34 | */ 35 | #define SYSCALL_WRAPPER_STACK_OFFSET (2 + 2 + 22) 36 | #define SYSCALL_WRAPPER_FRAME_SIZE (SYSCALL_WRAPPER_STACK_OFFSET + 2*32) 37 | #elif __riscv 38 | /* 3+2 regs(s0) | (1 << s1) | (1 << ra) pushed by the ECALL translation 39 | 27 general purpose regs pushed by syscall_wrapper 40 | 32 FP registers 41 | */ 42 | #define SYSCALL_WRAPPER_STACK_OFFSET (3+2+27) 43 | #define SYSCALL_WRAPPER_FRAME_SIZE (SYSCALL_WRAPPER_STACK_OFFSET + 32) 44 | #endif 45 | -------------------------------------------------------------------------------- /test/.gitignore: -------------------------------------------------------------------------------- 1 | mmap_munmap 2 | mprotect_exec 3 | self_modifying 4 | signals 5 | load_store 6 | -------------------------------------------------------------------------------- /test/arm_insts/v8.1/CASPx.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define FIRST_VAL 42 7 | #define SECOND_VAL 6 8 | #define FIRST_REPLACE 32 9 | #define SECOND_REPLACE 56 10 | 11 | void test_standard() { 12 | uint64_t *val_64 = (uint64_t *)malloc(2*sizeof(uint64_t)); 13 | *val_64 = FIRST_VAL; 14 | *(val_64+1) = SECOND_VAL; 15 | asm ( 16 | "mov x2, %0\n\t" 17 | "mov x3, %1\n\t" 18 | "mov x4, %2\n\t" 19 | "mov x5, %3\n\t" 20 | "mov x6, %4\n\t" 21 | "casp x2,x3,x4,x5,[x6]\n\t" 22 | :: "I"(FIRST_VAL), "I"(SECOND_VAL), "I"(FIRST_REPLACE), "I"(SECOND_REPLACE), "r"(val_64) 23 | ); 24 | assert(*val_64 == FIRST_REPLACE); 25 | assert(*(val_64+1) == SECOND_REPLACE); 26 | 27 | *val_64 = FIRST_VAL; 28 | *(val_64+1) = SECOND_VAL; 29 | asm ( 30 | "mov x2, %0\n\t" 31 | "mov x3, %1\n\t" 32 | "mov x4, %2\n\t" 33 | "mov x5, %3\n\t" 34 | "mov x6, %4\n\t" 35 | "caspa x2,x3,x4,x5,[x6]\n\t" 36 | :: "I"(FIRST_VAL), "I"(SECOND_VAL), "I"(FIRST_REPLACE), "I"(SECOND_REPLACE), "r"(val_64) 37 | ); 38 | assert(*val_64 == FIRST_REPLACE); 39 | assert(*(val_64+1) == SECOND_REPLACE); 40 | 41 | *val_64 = FIRST_VAL; 42 | *(val_64+1) = SECOND_VAL; 43 | asm ( 44 | "mov x2, %0\n\t" 45 | "mov x3, %1\n\t" 46 | "mov x4, %2\n\t" 47 | "mov x5, %3\n\t" 48 | "mov x6, %4\n\t" 49 | "caspal x2,x3,x4,x5,[x6]\n\t" 50 | :: "I"(FIRST_VAL), "I"(SECOND_VAL), "I"(FIRST_REPLACE), "I"(SECOND_REPLACE), "r"(val_64) 51 | ); 52 | assert(*val_64 == FIRST_REPLACE); 53 | assert(*(val_64+1) == SECOND_REPLACE); 54 | 55 | *val_64 = FIRST_VAL; 56 | *(val_64+1) = SECOND_VAL; 57 | asm ( 58 | "mov x2, %0\n\t" 59 | "mov x3, %1\n\t" 60 | "mov x4, %2\n\t" 61 | "mov x5, %3\n\t" 62 | "mov x6, %4\n\t" 63 | "caspl x2,x3,x4,x5,[x6]\n\t" 64 | :: "I"(FIRST_VAL), "I"(SECOND_VAL), "I"(FIRST_REPLACE), "I"(SECOND_REPLACE), "r"(val_64) 65 | ); 66 | assert(*val_64 == FIRST_REPLACE); 67 | assert(*(val_64+1) == SECOND_REPLACE); 68 | 69 | free(val_64); 70 | } 71 | 72 | int main() { 73 | test_standard(); 74 | fprintf(stderr, "%s\n", "Test passed."); 75 | return 0; 76 | } 77 | -------------------------------------------------------------------------------- /test/arm_insts/v8.1/CASx.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define FIRST_VAL 42 7 | #define SECOND_VAL 6 8 | #define SUCCESS_VAL 6 9 | 10 | void test_standard() { 11 | uint64_t *val_64 = (uint64_t *)malloc(sizeof(uint64_t)); 12 | *val_64 = FIRST_VAL; 13 | asm ( 14 | "mov x3, %0\n\t" 15 | "mov x5, %1\n\t" 16 | "mov x4, %2\n\t" 17 | "cas x3,x5,[x4]\n\t" 18 | :: "I"(FIRST_VAL), "I"(SECOND_VAL), "r"(val_64) 19 | ); 20 | assert(*val_64 == SECOND_VAL); 21 | 22 | asm ( 23 | "mov x3, %0\n\t" 24 | "mov x5, %1\n\t" 25 | "mov x4, %2\n\t" 26 | "casa x3,x5,[x4]\n\t" 27 | :: "I"(SECOND_VAL), "I"(SECOND_VAL+1), "r"(val_64) 28 | ); 29 | assert(*val_64 == SECOND_VAL+1); 30 | 31 | asm ( 32 | "mov x3, %0\n\t" 33 | "mov x5, %1\n\t" 34 | "mov x4, %2\n\t" 35 | "casal x3,x5,[x4]\n\t" 36 | :: "I"(SECOND_VAL+1), "I"(SECOND_VAL+2), "r"(val_64) 37 | ); 38 | assert(*val_64 == SECOND_VAL+2); 39 | 40 | asm ( 41 | "mov x3, %0\n\t" 42 | "mov x5, %1\n\t" 43 | "mov x4, %2\n\t" 44 | "casl x3,x5,[x4]\n\t" 45 | :: "I"(SECOND_VAL+2), "I"(SECOND_VAL+3), "r"(val_64) 46 | ); 47 | assert(*val_64 == SECOND_VAL+3); 48 | 49 | free(val_64); 50 | } 51 | 52 | void test_byte() { 53 | uint8_t *val_8 = (uint8_t *)malloc(sizeof(uint8_t)); 54 | *val_8 = FIRST_VAL; 55 | asm ( 56 | "mov w3, %0\n\t" 57 | "mov w5, %1\n\t" 58 | "mov x4, %2\n\t" 59 | "casb w3,w5,[x4]\n\t" 60 | :: "I"(FIRST_VAL), "I"(SECOND_VAL), "r"(val_8) 61 | ); 62 | assert(*val_8 == SECOND_VAL); 63 | 64 | asm ( 65 | "mov w3, %0\n\t" 66 | "mov w5, %1\n\t" 67 | "mov x4, %2\n\t" 68 | "casab w3,w5,[x4]\n\t" 69 | :: "I"(SECOND_VAL), "I"(SECOND_VAL+1), "r"(val_8) 70 | ); 71 | assert(*val_8 == SECOND_VAL+1); 72 | 73 | asm ( 74 | "mov w3, %0\n\t" 75 | "mov w5, %1\n\t" 76 | "mov x4, %2\n\t" 77 | "casalb w3,w5,[x4]\n\t" 78 | :: "I"(SECOND_VAL+1), "I"(SECOND_VAL+2), "r"(val_8) 79 | ); 80 | assert(*val_8 == SECOND_VAL+2); 81 | 82 | asm ( 83 | "mov w3, %0\n\t" 84 | "mov w5, %1\n\t" 85 | "mov x4, %2\n\t" 86 | "caslb w3,w5,[x4]\n\t" 87 | :: "I"(SECOND_VAL+2), "I"(SECOND_VAL+3), "r"(val_8) 88 | ); 89 | assert(*val_8 == SECOND_VAL+3); 90 | 91 | free(val_8); 92 | } 93 | 94 | void test_halfword() { 95 | uint32_t *val_32 = (uint32_t *)malloc(sizeof(uint32_t)); 96 | *val_32 = FIRST_VAL; 97 | asm ( 98 | "mov w3, %0\n\t" 99 | "mov w5, %1\n\t" 100 | "mov x4, %2\n\t" 101 | "cash w3,w5,[x4]\n\t" 102 | :: "I"(FIRST_VAL), "I"(SECOND_VAL), "r"(val_32) 103 | ); 104 | assert(*val_32 == SECOND_VAL); 105 | 106 | asm ( 107 | "mov w3, %0\n\t" 108 | "mov w5, %1\n\t" 109 | "mov x4, %2\n\t" 110 | "casah w3,w5,[x4]\n\t" 111 | :: "I"(SECOND_VAL), "I"(SECOND_VAL+1), "r"(val_32) 112 | ); 113 | assert(*val_32 == SECOND_VAL+1); 114 | 115 | asm ( 116 | "mov w3, %0\n\t" 117 | "mov w5, %1\n\t" 118 | "mov x4, %2\n\t" 119 | "casalh w3,w5,[x4]\n\t" 120 | :: "I"(SECOND_VAL+1), "I"(SECOND_VAL+2), "r"(val_32) 121 | ); 122 | assert(*val_32 == SECOND_VAL+2); 123 | 124 | asm ( 125 | "mov w3, %0\n\t" 126 | "mov w5, %1\n\t" 127 | "mov x4, %2\n\t" 128 | "caslh w3,w5,[x4]\n\t" 129 | :: "I"(SECOND_VAL+2), "I"(SECOND_VAL+3), "r"(val_32) 130 | ); 131 | assert(*val_32 == SECOND_VAL+3); 132 | 133 | free(val_32); 134 | } 135 | 136 | int main() { 137 | test_standard(); 138 | test_byte(); 139 | test_halfword(); 140 | fprintf(stderr, "%s\n", "Test passed."); 141 | return 0; 142 | } 143 | -------------------------------------------------------------------------------- /test/arm_insts/v8.1/LDADDx.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define START_VAL 60 7 | #define CHANGE_VAL 1 8 | 9 | void test_standard() { 10 | uint64_t *val_64 = (uint64_t *)malloc(sizeof(uint64_t)); 11 | *val_64 = START_VAL; 12 | asm ( 13 | "mov x3, %0\n\t" 14 | "mov x4, %1\n\t" 15 | "ldadd x3,x3,[x4]\n\t" 16 | :: "I"(CHANGE_VAL), "r"(val_64) 17 | ); 18 | assert(*val_64 == START_VAL+CHANGE_VAL); 19 | 20 | asm ( 21 | "mov x3, %0\n\t" 22 | "mov x4, %1\n\t" 23 | "ldadda x3,x3,[x4]\n\t" 24 | :: "I"(CHANGE_VAL), "r"(val_64) 25 | ); 26 | assert(*val_64 == START_VAL+(2*CHANGE_VAL)); 27 | 28 | asm ( 29 | "mov x3, %0\n\t" 30 | "mov x4, %1\n\t" 31 | "ldaddal x3,x3,[x4]\n\t" 32 | :: "I"(CHANGE_VAL), "r"(val_64) 33 | ); 34 | assert(*val_64 == START_VAL+(3*CHANGE_VAL)); 35 | 36 | asm ( 37 | "mov x3, %0\n\t" 38 | "mov x4, %1\n\t" 39 | "ldaddl x3,x3,[x4]\n\t" 40 | :: "I"(CHANGE_VAL), "r"(val_64) 41 | ); 42 | assert(*val_64 == START_VAL+(4*CHANGE_VAL)); 43 | 44 | free(val_64); 45 | } 46 | 47 | void test_byte() { 48 | uint8_t *val_8 = (uint8_t *)malloc(sizeof(uint8_t)); 49 | *val_8 = START_VAL; 50 | asm ( 51 | "mov w3, %0\n\t" 52 | "mov x4, %1\n\t" 53 | "ldaddb w3,w3,[x4]\n\t" 54 | :: "I"(CHANGE_VAL), "r"(val_8) 55 | ); 56 | assert(*val_8 == START_VAL+CHANGE_VAL); 57 | 58 | asm ( 59 | "mov w3, %0\n\t" 60 | "mov x4, %1\n\t" 61 | "ldaddab w3,w3,[x4]\n\t" 62 | :: "I"(CHANGE_VAL), "r"(val_8) 63 | ); 64 | assert(*val_8 == START_VAL+(2*CHANGE_VAL)); 65 | 66 | asm ( 67 | "mov w3, %0\n\t" 68 | "mov x4, %1\n\t" 69 | "ldaddalb w3,w3,[x4]\n\t" 70 | :: "I"(CHANGE_VAL), "r"(val_8) 71 | ); 72 | assert(*val_8 == START_VAL+(3*CHANGE_VAL)); 73 | 74 | asm ( 75 | "mov w3, %0\n\t" 76 | "mov x4, %1\n\t" 77 | "ldaddlb w3,w3,[x4]\n\t" 78 | :: "I"(CHANGE_VAL), "r"(val_8) 79 | ); 80 | assert(*val_8 == START_VAL+(4*CHANGE_VAL)); 81 | 82 | free(val_8); 83 | } 84 | 85 | void test_halfword() { 86 | uint32_t *val_32 = (uint32_t *)malloc(sizeof(uint32_t)); 87 | *val_32 = START_VAL; 88 | asm ( 89 | "mov w3, %0\n\t" 90 | "mov x4, %1\n\t" 91 | "ldaddh w3,w3,[x4]\n\t" 92 | :: "I"(CHANGE_VAL), "r"(val_32) 93 | ); 94 | assert(*val_32 == START_VAL+CHANGE_VAL); 95 | 96 | asm ( 97 | "mov w3, %0\n\t" 98 | "mov x4, %1\n\t" 99 | "ldaddah w3,w3,[x4]\n\t" 100 | :: "I"(CHANGE_VAL), "r"(val_32) 101 | ); 102 | assert(*val_32 == START_VAL+(2*CHANGE_VAL)); 103 | 104 | asm ( 105 | "mov w3, %0\n\t" 106 | "mov x4, %1\n\t" 107 | "ldaddalh w3,w3,[x4]\n\t" 108 | :: "I"(CHANGE_VAL), "r"(val_32) 109 | ); 110 | assert(*val_32 == START_VAL+(3*CHANGE_VAL)); 111 | 112 | asm ( 113 | "mov w3, %0\n\t" 114 | "mov x4, %1\n\t" 115 | "ldaddlh w3,w3,[x4]\n\t" 116 | :: "I"(CHANGE_VAL), "r"(val_32) 117 | ); 118 | assert(*val_32 == START_VAL+(4*CHANGE_VAL)); 119 | 120 | free(val_32); 121 | } 122 | 123 | int main() { 124 | test_standard(); 125 | test_byte(); 126 | test_halfword(); 127 | fprintf(stderr, "%s\n", "Test passed."); 128 | return 0; 129 | } 130 | -------------------------------------------------------------------------------- /test/arm_insts/v8.1/LDCLRx.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define START_VAL 1 7 | #define CHANGE_VAL 1 8 | 9 | void test_standard() { 10 | uint64_t *val_64 = (uint64_t *)malloc(sizeof(uint64_t)); 11 | *val_64 = START_VAL; 12 | asm ( 13 | "mov x3, %0\n\t" 14 | "mov x4, %1\n\t" 15 | "ldclr x3,x3,[x4]\n\t" 16 | :: "I"(CHANGE_VAL), "r"(val_64) 17 | ); 18 | assert(*val_64 == 0); 19 | 20 | asm ( 21 | "mov x3, %0\n\t" 22 | "mov x4, %1\n\t" 23 | "ldclra x3,x3,[x4]\n\t" 24 | :: "I"(CHANGE_VAL), "r"(val_64) 25 | ); 26 | assert(*val_64 == 0); 27 | 28 | asm ( 29 | "mov x3, %0\n\t" 30 | "mov x4, %1\n\t" 31 | "ldclral x3,x3,[x4]\n\t" 32 | :: "I"(CHANGE_VAL), "r"(val_64) 33 | ); 34 | assert(*val_64 == 0); 35 | 36 | asm ( 37 | "mov x3, %0\n\t" 38 | "mov x4, %1\n\t" 39 | "ldclrl x3,x3,[x4]\n\t" 40 | :: "I"(CHANGE_VAL), "r"(val_64) 41 | ); 42 | assert(*val_64 == 0); 43 | 44 | free(val_64); 45 | } 46 | 47 | void test_byte() { 48 | uint8_t *val_8 = (uint8_t *)malloc(sizeof(uint8_t)); 49 | *val_8 = START_VAL; 50 | asm ( 51 | "mov w3, %0\n\t" 52 | "mov x4, %1\n\t" 53 | "ldclrb w3,w3,[x4]\n\t" 54 | :: "I"(CHANGE_VAL), "r"(val_8) 55 | ); 56 | assert(*val_8 == 0); 57 | 58 | asm ( 59 | "mov w3, %0\n\t" 60 | "mov x4, %1\n\t" 61 | "ldclrab w3,w3,[x4]\n\t" 62 | :: "I"(CHANGE_VAL), "r"(val_8) 63 | ); 64 | assert(*val_8 == 0); 65 | 66 | asm ( 67 | "mov w3, %0\n\t" 68 | "mov x4, %1\n\t" 69 | "ldclralb w3,w3,[x4]\n\t" 70 | :: "I"(CHANGE_VAL), "r"(val_8) 71 | ); 72 | assert(*val_8 == 0); 73 | 74 | asm ( 75 | "mov w3, %0\n\t" 76 | "mov x4, %1\n\t" 77 | "ldclrlb w3,w3,[x4]\n\t" 78 | :: "I"(CHANGE_VAL), "r"(val_8) 79 | ); 80 | assert(*val_8 == 0); 81 | 82 | free(val_8); 83 | } 84 | 85 | void test_halfword() { 86 | uint32_t *val_32 = (uint32_t *)malloc(sizeof(uint32_t)); 87 | *val_32 = START_VAL; 88 | asm ( 89 | "mov w3, %0\n\t" 90 | "mov x4, %1\n\t" 91 | "ldclrh w3,w3,[x4]\n\t" 92 | :: "I"(CHANGE_VAL), "r"(val_32) 93 | ); 94 | assert(*val_32 == 0); 95 | 96 | asm ( 97 | "mov w3, %0\n\t" 98 | "mov x4, %1\n\t" 99 | "ldclrah w3,w3,[x4]\n\t" 100 | :: "I"(CHANGE_VAL), "r"(val_32) 101 | ); 102 | assert(*val_32 == 0); 103 | 104 | asm ( 105 | "mov w3, %0\n\t" 106 | "mov x4, %1\n\t" 107 | "ldclralh w3,w3,[x4]\n\t" 108 | :: "I"(CHANGE_VAL), "r"(val_32) 109 | ); 110 | assert(*val_32 == 0); 111 | 112 | asm ( 113 | "mov w3, %0\n\t" 114 | "mov x4, %1\n\t" 115 | "ldclrlh w3,w3,[x4]\n\t" 116 | :: "I"(CHANGE_VAL), "r"(val_32) 117 | ); 118 | assert(*val_32 == 0); 119 | 120 | free(val_32); 121 | } 122 | 123 | int main() { 124 | test_standard(); 125 | test_byte(); 126 | test_halfword(); 127 | fprintf(stderr, "%s\n", "Test passed."); 128 | return 0; 129 | } 130 | -------------------------------------------------------------------------------- /test/arm_insts/v8.1/LDEORx.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define START_VAL 1 7 | #define CHANGE_VAL 1 8 | 9 | void test_standard() { 10 | uint64_t *val_64 = (uint64_t *)malloc(sizeof(uint64_t)); 11 | *val_64 = START_VAL; 12 | asm ( 13 | "mov x3, %0\n\t" 14 | "mov x4, %1\n\t" 15 | "ldeor x3,x3,[x4]\n\t" 16 | :: "I"(CHANGE_VAL), "r"(val_64) 17 | ); 18 | assert(*val_64 == 0); 19 | 20 | asm ( 21 | "mov x3, %0\n\t" 22 | "mov x4, %1\n\t" 23 | "ldeora x3,x3,[x4]\n\t" 24 | :: "I"(CHANGE_VAL), "r"(val_64) 25 | ); 26 | assert(*val_64 == 1); 27 | 28 | asm ( 29 | "mov x3, %0\n\t" 30 | "mov x4, %1\n\t" 31 | "ldeoral x3,x3,[x4]\n\t" 32 | :: "I"(CHANGE_VAL), "r"(val_64) 33 | ); 34 | assert(*val_64 == 0); 35 | 36 | asm ( 37 | "mov x3, %0\n\t" 38 | "mov x4, %1\n\t" 39 | "ldeorl x3,x3,[x4]\n\t" 40 | :: "I"(CHANGE_VAL), "r"(val_64) 41 | ); 42 | assert(*val_64 == 1); 43 | 44 | free(val_64); 45 | } 46 | 47 | void test_byte() { 48 | uint8_t *val_8 = (uint8_t *)malloc(sizeof(uint8_t)); 49 | *val_8 = START_VAL; 50 | asm ( 51 | "mov w3, %0\n\t" 52 | "mov x4, %1\n\t" 53 | "ldeorb w3,w3,[x4]\n\t" 54 | :: "I"(CHANGE_VAL), "r"(val_8) 55 | ); 56 | assert(*val_8 == 0); 57 | 58 | asm ( 59 | "mov w3, %0\n\t" 60 | "mov x4, %1\n\t" 61 | "ldeorab w3,w3,[x4]\n\t" 62 | :: "I"(CHANGE_VAL), "r"(val_8) 63 | ); 64 | assert(*val_8 == 1); 65 | 66 | asm ( 67 | "mov w3, %0\n\t" 68 | "mov x4, %1\n\t" 69 | "ldeoralb w3,w3,[x4]\n\t" 70 | :: "I"(CHANGE_VAL), "r"(val_8) 71 | ); 72 | assert(*val_8 == 0); 73 | 74 | asm ( 75 | "mov w3, %0\n\t" 76 | "mov x4, %1\n\t" 77 | "ldeorlb w3,w3,[x4]\n\t" 78 | :: "I"(CHANGE_VAL), "r"(val_8) 79 | ); 80 | assert(*val_8 == 1); 81 | 82 | free(val_8); 83 | } 84 | 85 | void test_halfword() { 86 | uint32_t *val_32 = (uint32_t *)malloc(sizeof(uint32_t)); 87 | *val_32 = START_VAL; 88 | asm ( 89 | "mov w3, %0\n\t" 90 | "mov x4, %1\n\t" 91 | "ldeorh w3,w3,[x4]\n\t" 92 | :: "I"(CHANGE_VAL), "r"(val_32) 93 | ); 94 | assert(*val_32 == 0); 95 | 96 | asm ( 97 | "mov w3, %0\n\t" 98 | "mov x4, %1\n\t" 99 | "ldeorah w3,w3,[x4]\n\t" 100 | :: "I"(CHANGE_VAL), "r"(val_32) 101 | ); 102 | assert(*val_32 == 1); 103 | 104 | asm ( 105 | "mov w3, %0\n\t" 106 | "mov x4, %1\n\t" 107 | "ldeoralh w3,w3,[x4]\n\t" 108 | :: "I"(CHANGE_VAL), "r"(val_32) 109 | ); 110 | assert(*val_32 == 0); 111 | 112 | asm ( 113 | "mov w3, %0\n\t" 114 | "mov x4, %1\n\t" 115 | "ldeorlh w3,w3,[x4]\n\t" 116 | :: "I"(CHANGE_VAL), "r"(val_32) 117 | ); 118 | assert(*val_32 == 1); 119 | 120 | free(val_32); 121 | } 122 | 123 | int main() { 124 | test_standard(); 125 | test_byte(); 126 | test_halfword(); 127 | fprintf(stderr, "%s\n", "Test passed."); 128 | return 0; 129 | } 130 | -------------------------------------------------------------------------------- /test/arm_insts/v8.1/LDLARx.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define FIRST_VAL 42 7 | 8 | void test_standard() { 9 | uint64_t *val_64 = (uint64_t *)malloc(sizeof(uint64_t)); 10 | uint64_t *result_64 = (uint64_t *)malloc(sizeof(uint64_t)); 11 | *val_64 = FIRST_VAL; 12 | *result_64 = 0; 13 | asm ( 14 | "mov x4, %0\n\t" 15 | "mov x5, %1\n\t" 16 | "ldlar x3,[x4]\n\t" 17 | "str x3, [x5]\n\t" 18 | :: "r"(val_64), "r"(result_64) 19 | ); 20 | assert(*result_64 == FIRST_VAL); 21 | 22 | free(val_64); 23 | free(result_64); 24 | } 25 | 26 | void test_byte() { 27 | uint8_t *val_8 = (uint8_t *)malloc(sizeof(uint8_t)); 28 | uint8_t *result_8 = (uint8_t *)malloc(sizeof(uint8_t)); 29 | *val_8 = FIRST_VAL; 30 | *result_8 = 0; 31 | asm ( 32 | "mov x4, %0\n\t" 33 | "mov x5, %1\n\t" 34 | "ldlarb w3,[x4]\n\t" 35 | "strb w3, [x5]\n\t" 36 | :: "r"(val_8), "r"(result_8) 37 | ); 38 | assert(*result_8 == FIRST_VAL); 39 | 40 | free(val_8); 41 | free(result_8); 42 | } 43 | 44 | void test_halfword() { 45 | uint32_t *val_32 = (uint32_t *)malloc(sizeof(uint32_t)); 46 | uint32_t *result_32 = (uint32_t *)malloc(sizeof(uint32_t)); 47 | *val_32 = FIRST_VAL; 48 | *result_32 = 0; 49 | asm ( 50 | "mov x4, %0\n\t" 51 | "mov x5, %1\n\t" 52 | "ldlarh w3,[x4]\n\t" 53 | "strh w3, [x5]\n\t" 54 | :: "r"(val_32), "r"(result_32) 55 | ); 56 | assert(*result_32 == FIRST_VAL); 57 | 58 | free(val_32); 59 | free(result_32); 60 | } 61 | 62 | int main() { 63 | test_standard(); 64 | test_byte(); 65 | test_halfword(); 66 | fprintf(stderr, "%s\n", "Test passed."); 67 | return 0; 68 | } 69 | -------------------------------------------------------------------------------- /test/arm_insts/v8.1/LDSETx.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define START_VAL 1 7 | #define CHANGE_VAL 1 8 | 9 | void test_standard() { 10 | uint64_t *val_64 = (uint64_t *)malloc(sizeof(uint64_t)); 11 | *val_64 = START_VAL; 12 | asm ( 13 | "mov x3, %0\n\t" 14 | "mov x4, %1\n\t" 15 | "ldset x3,x3,[x4]\n\t" 16 | :: "I"(CHANGE_VAL), "r"(val_64) 17 | ); 18 | assert(*val_64 == 1); 19 | 20 | asm ( 21 | "mov x3, %0\n\t" 22 | "mov x4, %1\n\t" 23 | "ldseta x3,x3,[x4]\n\t" 24 | :: "I"(CHANGE_VAL), "r"(val_64) 25 | ); 26 | assert(*val_64 == 1); 27 | 28 | asm ( 29 | "mov x3, %0\n\t" 30 | "mov x4, %1\n\t" 31 | "ldsetal x3,x3,[x4]\n\t" 32 | :: "I"(CHANGE_VAL), "r"(val_64) 33 | ); 34 | assert(*val_64 == 1); 35 | 36 | asm ( 37 | "mov x3, %0\n\t" 38 | "mov x4, %1\n\t" 39 | "ldsetl x3,x3,[x4]\n\t" 40 | :: "I"(CHANGE_VAL), "r"(val_64) 41 | ); 42 | assert(*val_64 == 1); 43 | 44 | free(val_64); 45 | } 46 | 47 | void test_byte() { 48 | uint8_t *val_8 = (uint8_t *)malloc(sizeof(uint8_t)); 49 | *val_8 = START_VAL; 50 | asm ( 51 | "mov w3, %0\n\t" 52 | "mov x4, %1\n\t" 53 | "ldsetb w3,w3,[x4]\n\t" 54 | :: "I"(CHANGE_VAL), "r"(val_8) 55 | ); 56 | assert(*val_8 == 1); 57 | 58 | asm ( 59 | "mov w3, %0\n\t" 60 | "mov x4, %1\n\t" 61 | "ldsetab w3,w3,[x4]\n\t" 62 | :: "I"(CHANGE_VAL), "r"(val_8) 63 | ); 64 | assert(*val_8 == 1); 65 | 66 | asm ( 67 | "mov w3, %0\n\t" 68 | "mov x4, %1\n\t" 69 | "ldsetalb w3,w3,[x4]\n\t" 70 | :: "I"(CHANGE_VAL), "r"(val_8) 71 | ); 72 | assert(*val_8 == 1); 73 | 74 | asm ( 75 | "mov w3, %0\n\t" 76 | "mov x4, %1\n\t" 77 | "ldsetlb w3,w3,[x4]\n\t" 78 | :: "I"(CHANGE_VAL), "r"(val_8) 79 | ); 80 | assert(*val_8 == 1); 81 | 82 | free(val_8); 83 | } 84 | 85 | void test_halfword() { 86 | uint32_t *val_32 = (uint32_t *)malloc(sizeof(uint32_t)); 87 | *val_32 = START_VAL; 88 | asm ( 89 | "mov w3, %0\n\t" 90 | "mov x4, %1\n\t" 91 | "ldseth w3,w3,[x4]\n\t" 92 | :: "I"(CHANGE_VAL), "r"(val_32) 93 | ); 94 | assert(*val_32 == 1); 95 | 96 | asm ( 97 | "mov w3, %0\n\t" 98 | "mov x4, %1\n\t" 99 | "ldsetah w3,w3,[x4]\n\t" 100 | :: "I"(CHANGE_VAL), "r"(val_32) 101 | ); 102 | assert(*val_32 == 1); 103 | 104 | asm ( 105 | "mov w3, %0\n\t" 106 | "mov x4, %1\n\t" 107 | "ldsetalh w3,w3,[x4]\n\t" 108 | :: "I"(CHANGE_VAL), "r"(val_32) 109 | ); 110 | assert(*val_32 == 1); 111 | 112 | asm ( 113 | "mov w3, %0\n\t" 114 | "mov x4, %1\n\t" 115 | "ldsetlh w3,w3,[x4]\n\t" 116 | :: "I"(CHANGE_VAL), "r"(val_32) 117 | ); 118 | assert(*val_32 == 1); 119 | 120 | free(val_32); 121 | } 122 | 123 | int main() { 124 | test_standard(); 125 | test_byte(); 126 | test_halfword(); 127 | fprintf(stderr, "%s\n", "Test passed."); 128 | return 0; 129 | } 130 | -------------------------------------------------------------------------------- /test/arm_insts/v8.1/LDSMAXx.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define FIRST_VAL 42 7 | #define SECOND_VAL 43 8 | 9 | void test_standard() { 10 | uint64_t *val_64 = (uint64_t *)malloc(sizeof(uint64_t)); 11 | *val_64 = FIRST_VAL; 12 | asm ( 13 | "mov x3, %0\n\t" 14 | "mov x4, %1\n\t" 15 | "ldsmax x3,x3,[x4]\n\t" 16 | :: "I"(SECOND_VAL), "r"(val_64) 17 | ); 18 | assert(*val_64 == SECOND_VAL); 19 | 20 | asm ( 21 | "mov x3, %0\n\t" 22 | "mov x4, %1\n\t" 23 | "ldsmaxa x3,x3,[x4]\n\t" 24 | :: "I"(SECOND_VAL+1), "r"(val_64) 25 | ); 26 | assert(*val_64 == SECOND_VAL+1); 27 | 28 | asm ( 29 | "mov x3, %0\n\t" 30 | "mov x4, %1\n\t" 31 | "ldsmaxal x3,x3,[x4]\n\t" 32 | :: "I"(SECOND_VAL+2), "r"(val_64) 33 | ); 34 | assert(*val_64 == SECOND_VAL+2); 35 | 36 | asm ( 37 | "mov x3, %0\n\t" 38 | "mov x4, %1\n\t" 39 | "ldsmaxl x3,x3,[x4]\n\t" 40 | :: "I"(SECOND_VAL+3), "r"(val_64) 41 | ); 42 | assert(*val_64 == SECOND_VAL+3); 43 | 44 | free(val_64); 45 | } 46 | 47 | void test_byte() { 48 | uint8_t *val_8 = (uint8_t *)malloc(sizeof(uint8_t)); 49 | *val_8 = FIRST_VAL; 50 | asm ( 51 | "mov w3, %0\n\t" 52 | "mov x4, %1\n\t" 53 | "ldsmaxb w3,w3,[x4]\n\t" 54 | :: "I"(SECOND_VAL), "r"(val_8) 55 | ); 56 | assert(*val_8 == SECOND_VAL); 57 | 58 | asm ( 59 | "mov w3, %0\n\t" 60 | "mov x4, %1\n\t" 61 | "ldsmaxab w3,w3,[x4]\n\t" 62 | :: "I"(SECOND_VAL+1), "r"(val_8) 63 | ); 64 | assert(*val_8 == SECOND_VAL+1); 65 | 66 | asm ( 67 | "mov w3, %0\n\t" 68 | "mov x4, %1\n\t" 69 | "ldsmaxalb w3,w3,[x4]\n\t" 70 | :: "I"(SECOND_VAL+2), "r"(val_8) 71 | ); 72 | assert(*val_8 == SECOND_VAL+2); 73 | 74 | asm ( 75 | "mov w3, %0\n\t" 76 | "mov x4, %1\n\t" 77 | "ldsmaxlb w3,w3,[x4]\n\t" 78 | :: "I"(SECOND_VAL+3), "r"(val_8) 79 | ); 80 | assert(*val_8 == SECOND_VAL+3); 81 | 82 | free(val_8); 83 | } 84 | 85 | void test_halfword() { 86 | uint32_t *val_32 = (uint32_t *)malloc(sizeof(uint32_t)); 87 | *val_32 = FIRST_VAL; 88 | asm ( 89 | "mov w3, %0\n\t" 90 | "mov x4, %1\n\t" 91 | "ldsmaxh w3,w3,[x4]\n\t" 92 | :: "I"(SECOND_VAL), "r"(val_32) 93 | ); 94 | assert(*val_32 == SECOND_VAL); 95 | 96 | asm ( 97 | "mov w3, %0\n\t" 98 | "mov x4, %1\n\t" 99 | "ldsmaxah w3,w3,[x4]\n\t" 100 | :: "I"(SECOND_VAL+1), "r"(val_32) 101 | ); 102 | assert(*val_32 == SECOND_VAL+1); 103 | 104 | asm ( 105 | "mov w3, %0\n\t" 106 | "mov x4, %1\n\t" 107 | "ldsmaxalh w3,w3,[x4]\n\t" 108 | :: "I"(SECOND_VAL+2), "r"(val_32) 109 | ); 110 | assert(*val_32 == SECOND_VAL+2); 111 | 112 | asm ( 113 | "mov w3, %0\n\t" 114 | "mov x4, %1\n\t" 115 | "ldsmaxlh w3,w3,[x4]\n\t" 116 | :: "I"(SECOND_VAL+3), "r"(val_32) 117 | ); 118 | assert(*val_32 == SECOND_VAL+3); 119 | 120 | free(val_32); 121 | } 122 | 123 | int main() { 124 | test_standard(); 125 | test_byte(); 126 | test_halfword(); 127 | fprintf(stderr, "%s\n", "Test passed."); 128 | return 0; 129 | } 130 | -------------------------------------------------------------------------------- /test/arm_insts/v8.1/LDSMINx.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define FIRST_VAL 42 7 | #define SECOND_VAL 41 8 | 9 | void test_standard() { 10 | uint64_t *val_64 = (uint64_t *)malloc(sizeof(uint64_t)); 11 | *val_64 = FIRST_VAL; 12 | asm ( 13 | "mov x3, %0\n\t" 14 | "mov x4, %1\n\t" 15 | "ldsmin x3,x3,[x4]\n\t" 16 | :: "I"(SECOND_VAL), "r"(val_64) 17 | ); 18 | assert(*val_64 == SECOND_VAL); 19 | 20 | asm ( 21 | "mov x3, %0\n\t" 22 | "mov x4, %1\n\t" 23 | "ldsmina x3,x3,[x4]\n\t" 24 | :: "I"(SECOND_VAL-1), "r"(val_64) 25 | ); 26 | assert(*val_64 == SECOND_VAL-1); 27 | 28 | asm ( 29 | "mov x3, %0\n\t" 30 | "mov x4, %1\n\t" 31 | "ldsminal x3,x3,[x4]\n\t" 32 | :: "I"(SECOND_VAL-2), "r"(val_64) 33 | ); 34 | assert(*val_64 == SECOND_VAL-2); 35 | 36 | asm ( 37 | "mov x3, %0\n\t" 38 | "mov x4, %1\n\t" 39 | "ldsminl x3,x3,[x4]\n\t" 40 | :: "I"(SECOND_VAL-3), "r"(val_64) 41 | ); 42 | assert(*val_64 == SECOND_VAL-3); 43 | 44 | free(val_64); 45 | } 46 | 47 | void test_byte() { 48 | uint8_t *val_8 = (uint8_t *)malloc(sizeof(uint8_t)); 49 | *val_8 = FIRST_VAL; 50 | asm ( 51 | "mov w3, %0\n\t" 52 | "mov x4, %1\n\t" 53 | "ldsminb w3,w3,[x4]\n\t" 54 | :: "I"(SECOND_VAL), "r"(val_8) 55 | ); 56 | assert(*val_8 == SECOND_VAL); 57 | 58 | asm ( 59 | "mov w3, %0\n\t" 60 | "mov x4, %1\n\t" 61 | "ldsminab w3,w3,[x4]\n\t" 62 | :: "I"(SECOND_VAL-1), "r"(val_8) 63 | ); 64 | assert(*val_8 == SECOND_VAL-1); 65 | 66 | asm ( 67 | "mov w3, %0\n\t" 68 | "mov x4, %1\n\t" 69 | "ldsminalb w3,w3,[x4]\n\t" 70 | :: "I"(SECOND_VAL-2), "r"(val_8) 71 | ); 72 | assert(*val_8 == SECOND_VAL-2); 73 | 74 | asm ( 75 | "mov w3, %0\n\t" 76 | "mov x4, %1\n\t" 77 | "ldsminlb w3,w3,[x4]\n\t" 78 | :: "I"(SECOND_VAL-3), "r"(val_8) 79 | ); 80 | assert(*val_8 == SECOND_VAL-3); 81 | 82 | free(val_8); 83 | } 84 | 85 | void test_halfword() { 86 | uint32_t *val_32 = (uint32_t *)malloc(sizeof(uint32_t)); 87 | *val_32 = FIRST_VAL; 88 | asm ( 89 | "mov w3, %0\n\t" 90 | "mov x4, %1\n\t" 91 | "ldsminh w3,w3,[x4]\n\t" 92 | :: "I"(SECOND_VAL), "r"(val_32) 93 | ); 94 | assert(*val_32 == SECOND_VAL); 95 | 96 | asm ( 97 | "mov w3, %0\n\t" 98 | "mov x4, %1\n\t" 99 | "ldsminah w3,w3,[x4]\n\t" 100 | :: "I"(SECOND_VAL-1), "r"(val_32) 101 | ); 102 | assert(*val_32 == SECOND_VAL-1); 103 | 104 | asm ( 105 | "mov w3, %0\n\t" 106 | "mov x4, %1\n\t" 107 | "ldsminalh w3,w3,[x4]\n\t" 108 | :: "I"(SECOND_VAL-2), "r"(val_32) 109 | ); 110 | assert(*val_32 == SECOND_VAL-2); 111 | 112 | asm ( 113 | "mov w3, %0\n\t" 114 | "mov x4, %1\n\t" 115 | "ldsminlh w3,w3,[x4]\n\t" 116 | :: "I"(SECOND_VAL-3), "r"(val_32) 117 | ); 118 | assert(*val_32 == SECOND_VAL-3); 119 | 120 | free(val_32); 121 | } 122 | 123 | int main() { 124 | test_standard(); 125 | test_byte(); 126 | test_halfword(); 127 | fprintf(stderr, "%s\n", "Test passed."); 128 | return 0; 129 | } 130 | -------------------------------------------------------------------------------- /test/arm_insts/v8.1/LDUMAXx.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define FIRST_VAL 42 7 | #define SECOND_VAL 43 8 | 9 | void test_standard() { 10 | uint64_t *val_64 = (uint64_t *)malloc(sizeof(uint64_t)); 11 | *val_64 = FIRST_VAL; 12 | asm ( 13 | "mov x3, %0\n\t" 14 | "mov x4, %1\n\t" 15 | "ldumax x3,x3,[x4]\n\t" 16 | :: "I"(SECOND_VAL), "r"(val_64) 17 | ); 18 | assert(*val_64 == SECOND_VAL); 19 | 20 | asm ( 21 | "mov x3, %0\n\t" 22 | "mov x4, %1\n\t" 23 | "ldumaxa x3,x3,[x4]\n\t" 24 | :: "I"(SECOND_VAL+1), "r"(val_64) 25 | ); 26 | assert(*val_64 == SECOND_VAL+1); 27 | 28 | asm ( 29 | "mov x3, %0\n\t" 30 | "mov x4, %1\n\t" 31 | "ldumaxal x3,x3,[x4]\n\t" 32 | :: "I"(SECOND_VAL+2), "r"(val_64) 33 | ); 34 | assert(*val_64 == SECOND_VAL+2); 35 | 36 | asm ( 37 | "mov x3, %0\n\t" 38 | "mov x4, %1\n\t" 39 | "ldumaxl x3,x3,[x4]\n\t" 40 | :: "I"(SECOND_VAL+3), "r"(val_64) 41 | ); 42 | assert(*val_64 == SECOND_VAL+3); 43 | 44 | free(val_64); 45 | } 46 | 47 | void test_byte() { 48 | uint8_t *val_8 = (uint8_t *)malloc(sizeof(uint8_t)); 49 | *val_8 = FIRST_VAL; 50 | asm ( 51 | "mov w3, %0\n\t" 52 | "mov x4, %1\n\t" 53 | "ldumaxb w3,w3,[x4]\n\t" 54 | :: "I"(SECOND_VAL), "r"(val_8) 55 | ); 56 | assert(*val_8 == SECOND_VAL); 57 | 58 | asm ( 59 | "mov w3, %0\n\t" 60 | "mov x4, %1\n\t" 61 | "ldumaxab w3,w3,[x4]\n\t" 62 | :: "I"(SECOND_VAL+1), "r"(val_8) 63 | ); 64 | assert(*val_8 == SECOND_VAL+1); 65 | 66 | asm ( 67 | "mov w3, %0\n\t" 68 | "mov x4, %1\n\t" 69 | "ldumaxalb w3,w3,[x4]\n\t" 70 | :: "I"(SECOND_VAL+2), "r"(val_8) 71 | ); 72 | assert(*val_8 == SECOND_VAL+2); 73 | 74 | asm ( 75 | "mov w3, %0\n\t" 76 | "mov x4, %1\n\t" 77 | "ldumaxlb w3,w3,[x4]\n\t" 78 | :: "I"(SECOND_VAL+3), "r"(val_8) 79 | ); 80 | assert(*val_8 == SECOND_VAL+3); 81 | 82 | free(val_8); 83 | } 84 | 85 | void test_halfword() { 86 | uint32_t *val_32 = (uint32_t *)malloc(sizeof(uint32_t)); 87 | *val_32 = FIRST_VAL; 88 | asm ( 89 | "mov w3, %0\n\t" 90 | "mov x4, %1\n\t" 91 | "ldumaxh w3,w3,[x4]\n\t" 92 | :: "I"(SECOND_VAL), "r"(val_32) 93 | ); 94 | assert(*val_32 == SECOND_VAL); 95 | 96 | asm ( 97 | "mov w3, %0\n\t" 98 | "mov x4, %1\n\t" 99 | "ldumaxah w3,w3,[x4]\n\t" 100 | :: "I"(SECOND_VAL+1), "r"(val_32) 101 | ); 102 | assert(*val_32 == SECOND_VAL+1); 103 | 104 | asm ( 105 | "mov w3, %0\n\t" 106 | "mov x4, %1\n\t" 107 | "ldumaxalh w3,w3,[x4]\n\t" 108 | :: "I"(SECOND_VAL+2), "r"(val_32) 109 | ); 110 | assert(*val_32 == SECOND_VAL+2); 111 | 112 | asm ( 113 | "mov w3, %0\n\t" 114 | "mov x4, %1\n\t" 115 | "ldumaxlh w3,w3,[x4]\n\t" 116 | :: "I"(SECOND_VAL+3), "r"(val_32) 117 | ); 118 | assert(*val_32 == SECOND_VAL+3); 119 | 120 | free(val_32); 121 | } 122 | 123 | int main() { 124 | test_standard(); 125 | test_byte(); 126 | test_halfword(); 127 | fprintf(stderr, "%s\n", "Test passed."); 128 | return 0; 129 | } 130 | -------------------------------------------------------------------------------- /test/arm_insts/v8.1/LDUMINx.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define FIRST_VAL 42 7 | #define SECOND_VAL 41 8 | 9 | void test_standard() { 10 | uint64_t *val_64 = (uint64_t *)malloc(sizeof(uint64_t)); 11 | *val_64 = FIRST_VAL; 12 | asm ( 13 | "mov x3, %0\n\t" 14 | "mov x4, %1\n\t" 15 | "ldumin x3,x3,[x4]\n\t" 16 | :: "I"(SECOND_VAL), "r"(val_64) 17 | ); 18 | assert(*val_64 == SECOND_VAL); 19 | 20 | asm ( 21 | "mov x3, %0\n\t" 22 | "mov x4, %1\n\t" 23 | "ldumina x3,x3,[x4]\n\t" 24 | :: "I"(SECOND_VAL-1), "r"(val_64) 25 | ); 26 | assert(*val_64 == SECOND_VAL-1); 27 | 28 | asm ( 29 | "mov x3, %0\n\t" 30 | "mov x4, %1\n\t" 31 | "lduminal x3,x3,[x4]\n\t" 32 | :: "I"(SECOND_VAL-2), "r"(val_64) 33 | ); 34 | assert(*val_64 == SECOND_VAL-2); 35 | 36 | asm ( 37 | "mov x3, %0\n\t" 38 | "mov x4, %1\n\t" 39 | "lduminl x3,x3,[x4]\n\t" 40 | :: "I"(SECOND_VAL-3), "r"(val_64) 41 | ); 42 | assert(*val_64 == SECOND_VAL-3); 43 | 44 | free(val_64); 45 | } 46 | 47 | void test_byte() { 48 | uint8_t *val_8 = (uint8_t *)malloc(sizeof(uint8_t)); 49 | *val_8 = FIRST_VAL; 50 | asm ( 51 | "mov w3, %0\n\t" 52 | "mov x4, %1\n\t" 53 | "lduminb w3,w3,[x4]\n\t" 54 | :: "I"(SECOND_VAL), "r"(val_8) 55 | ); 56 | assert(*val_8 == SECOND_VAL); 57 | 58 | asm ( 59 | "mov w3, %0\n\t" 60 | "mov x4, %1\n\t" 61 | "lduminab w3,w3,[x4]\n\t" 62 | :: "I"(SECOND_VAL-1), "r"(val_8) 63 | ); 64 | assert(*val_8 == SECOND_VAL-1); 65 | 66 | asm ( 67 | "mov w3, %0\n\t" 68 | "mov x4, %1\n\t" 69 | "lduminalb w3,w3,[x4]\n\t" 70 | :: "I"(SECOND_VAL-2), "r"(val_8) 71 | ); 72 | assert(*val_8 == SECOND_VAL-2); 73 | 74 | asm ( 75 | "mov w3, %0\n\t" 76 | "mov x4, %1\n\t" 77 | "lduminlb w3,w3,[x4]\n\t" 78 | :: "I"(SECOND_VAL-3), "r"(val_8) 79 | ); 80 | assert(*val_8 == SECOND_VAL-3); 81 | 82 | free(val_8); 83 | } 84 | 85 | void test_halfword() { 86 | uint32_t *val_32 = (uint32_t *)malloc(sizeof(uint32_t)); 87 | *val_32 = FIRST_VAL; 88 | asm ( 89 | "mov w3, %0\n\t" 90 | "mov x4, %1\n\t" 91 | "lduminh w3,w3,[x4]\n\t" 92 | :: "I"(SECOND_VAL), "r"(val_32) 93 | ); 94 | assert(*val_32 == SECOND_VAL); 95 | 96 | asm ( 97 | "mov w3, %0\n\t" 98 | "mov x4, %1\n\t" 99 | "lduminah w3,w3,[x4]\n\t" 100 | :: "I"(SECOND_VAL-1), "r"(val_32) 101 | ); 102 | assert(*val_32 == SECOND_VAL-1); 103 | 104 | asm ( 105 | "mov w3, %0\n\t" 106 | "mov x4, %1\n\t" 107 | "lduminalh w3,w3,[x4]\n\t" 108 | :: "I"(SECOND_VAL-2), "r"(val_32) 109 | ); 110 | assert(*val_32 == SECOND_VAL-2); 111 | 112 | asm ( 113 | "mov w3, %0\n\t" 114 | "mov x4, %1\n\t" 115 | "lduminlh w3,w3,[x4]\n\t" 116 | :: "I"(SECOND_VAL-3), "r"(val_32) 117 | ); 118 | assert(*val_32 == SECOND_VAL-3); 119 | 120 | free(val_32); 121 | } 122 | 123 | int main() { 124 | test_standard(); 125 | test_byte(); 126 | test_halfword(); 127 | fprintf(stderr, "%s\n", "Test passed."); 128 | return 0; 129 | } 130 | -------------------------------------------------------------------------------- /test/arm_insts/v8.1/SQRDMLxH.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void test_standard() { 7 | asm ( 8 | "movi v0.8b,3\n\t" 9 | "movi v1.8b,3\n\t" 10 | "movi v2.8b,3\n\t" 11 | "sqrdmlsh h0,h1,v2.h[1]\n\t" 12 | ); 13 | 14 | asm ( 15 | "movi v0.8b,3\n\t" 16 | "movi v1.8b,3\n\t" 17 | "movi v2.8b,3\n\t" 18 | "sqrdmlah h0,h1,v2.h[1]\n\t" 19 | ); 20 | } 21 | 22 | int main() { 23 | test_standard(); 24 | fprintf(stderr, "%s\n", "Test passed."); 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /test/arm_insts/v8.1/STADDx.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define START_VAL 60 7 | #define CHANGE_VAL 1 8 | 9 | void test_standard() { 10 | uint64_t *val_64 = (uint64_t *)malloc(sizeof(uint64_t)); 11 | *val_64 = START_VAL; 12 | asm ( 13 | "mov x3, %0\n\t" 14 | "mov x4, %1\n\t" 15 | "stadd x3,[x4]\n\t" 16 | :: "I"(CHANGE_VAL), "r"(val_64) 17 | ); 18 | assert(*val_64 == START_VAL+CHANGE_VAL); 19 | 20 | asm ( 21 | "mov x3, %0\n\t" 22 | "mov x4, %1\n\t" 23 | "staddl x3,[x4]\n\t" 24 | :: "I"(CHANGE_VAL), "r"(val_64) 25 | ); 26 | assert(*val_64 == START_VAL+(2*CHANGE_VAL)); 27 | 28 | free(val_64); 29 | } 30 | 31 | void test_byte() { 32 | uint8_t *val_8 = (uint8_t *)malloc(sizeof(uint8_t)); 33 | *val_8 = START_VAL; 34 | asm ( 35 | "mov w3, %0\n\t" 36 | "mov x4, %1\n\t" 37 | "staddb w3,[x4]\n\t" 38 | :: "I"(CHANGE_VAL), "r"(val_8) 39 | ); 40 | assert(*val_8 == START_VAL+CHANGE_VAL); 41 | 42 | asm ( 43 | "mov w3, %0\n\t" 44 | "mov x4, %1\n\t" 45 | "staddlb w3,[x4]\n\t" 46 | :: "I"(CHANGE_VAL), "r"(val_8) 47 | ); 48 | assert(*val_8 == START_VAL+(2*CHANGE_VAL)); 49 | 50 | free(val_8); 51 | } 52 | 53 | void test_halfword() { 54 | uint32_t *val_32 = (uint32_t *)malloc(sizeof(uint32_t)); 55 | *val_32 = START_VAL; 56 | asm ( 57 | "mov w3, %0\n\t" 58 | "mov x4, %1\n\t" 59 | "staddh w3,[x4]\n\t" 60 | :: "I"(CHANGE_VAL), "r"(val_32) 61 | ); 62 | assert(*val_32 == START_VAL+CHANGE_VAL); 63 | 64 | asm ( 65 | "mov w3, %0\n\t" 66 | "mov x4, %1\n\t" 67 | "staddlh w3,[x4]\n\t" 68 | :: "I"(CHANGE_VAL), "r"(val_32) 69 | ); 70 | assert(*val_32 == START_VAL+(2*CHANGE_VAL)); 71 | 72 | free(val_32); 73 | } 74 | 75 | int main() { 76 | test_standard(); 77 | test_byte(); 78 | test_halfword(); 79 | fprintf(stderr, "%s\n", "Test passed."); 80 | return 0; 81 | } 82 | -------------------------------------------------------------------------------- /test/arm_insts/v8.1/STCLRx.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define START_VAL 1 7 | #define CHANGE_VAL 1 8 | 9 | void test_standard() { 10 | uint64_t *val_64 = (uint64_t *)malloc(sizeof(uint64_t)); 11 | *val_64 = START_VAL; 12 | asm ( 13 | "mov x3, %0\n\t" 14 | "mov x4, %1\n\t" 15 | "stclr x3,[x4]\n\t" 16 | :: "I"(CHANGE_VAL), "r"(val_64) 17 | ); 18 | assert(*val_64 == 0); 19 | 20 | asm ( 21 | "mov x3, %0\n\t" 22 | "mov x4, %1\n\t" 23 | "stclrl x3,[x4]\n\t" 24 | :: "I"(CHANGE_VAL), "r"(val_64) 25 | ); 26 | assert(*val_64 == 0); 27 | 28 | free(val_64); 29 | } 30 | 31 | void test_byte() { 32 | uint8_t *val_8 = (uint8_t *)malloc(sizeof(uint8_t)); 33 | *val_8 = START_VAL; 34 | asm ( 35 | "mov w3, %0\n\t" 36 | "mov x4, %1\n\t" 37 | "stclrb w3,[x4]\n\t" 38 | :: "I"(CHANGE_VAL), "r"(val_8) 39 | ); 40 | assert(*val_8 == 0); 41 | 42 | asm ( 43 | "mov w3, %0\n\t" 44 | "mov x4, %1\n\t" 45 | "stclrlb w3,[x4]\n\t" 46 | :: "I"(CHANGE_VAL), "r"(val_8) 47 | ); 48 | assert(*val_8 == 0); 49 | 50 | free(val_8); 51 | } 52 | 53 | void test_halfword() { 54 | uint32_t *val_32 = (uint32_t *)malloc(sizeof(uint32_t)); 55 | *val_32 = START_VAL; 56 | asm ( 57 | "mov w3, %0\n\t" 58 | "mov x4, %1\n\t" 59 | "stclrh w3,[x4]\n\t" 60 | :: "I"(CHANGE_VAL), "r"(val_32) 61 | ); 62 | assert(*val_32 == 0); 63 | 64 | asm ( 65 | "mov w3, %0\n\t" 66 | "mov x4, %1\n\t" 67 | "stclrlh w3,[x4]\n\t" 68 | :: "I"(CHANGE_VAL), "r"(val_32) 69 | ); 70 | assert(*val_32 == 0); 71 | 72 | free(val_32); 73 | } 74 | 75 | int main() { 76 | test_standard(); 77 | test_byte(); 78 | test_halfword(); 79 | fprintf(stderr, "%s\n", "Test passed."); 80 | return 0; 81 | } 82 | -------------------------------------------------------------------------------- /test/arm_insts/v8.1/STEORx.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define START_VAL 1 7 | #define CHANGE_VAL 1 8 | 9 | void test_standard() { 10 | uint64_t *val_64 = (uint64_t *)malloc(sizeof(uint64_t)); 11 | *val_64 = START_VAL; 12 | asm ( 13 | "mov x3, %0\n\t" 14 | "mov x4, %1\n\t" 15 | "steor x3,[x4]\n\t" 16 | :: "I"(CHANGE_VAL), "r"(val_64) 17 | ); 18 | assert(*val_64 == 0); 19 | 20 | asm ( 21 | "mov x3, %0\n\t" 22 | "mov x4, %1\n\t" 23 | "steorl x3,[x4]\n\t" 24 | :: "I"(CHANGE_VAL), "r"(val_64) 25 | ); 26 | assert(*val_64 == 1); 27 | 28 | free(val_64); 29 | } 30 | 31 | void test_byte() { 32 | uint8_t *val_8 = (uint8_t *)malloc(sizeof(uint8_t)); 33 | *val_8 = START_VAL; 34 | asm ( 35 | "mov w3, %0\n\t" 36 | "mov x4, %1\n\t" 37 | "steorb w3,[x4]\n\t" 38 | :: "I"(CHANGE_VAL), "r"(val_8) 39 | ); 40 | assert(*val_8 == 0); 41 | 42 | asm ( 43 | "mov w3, %0\n\t" 44 | "mov x4, %1\n\t" 45 | "steorlb w3,[x4]\n\t" 46 | :: "I"(CHANGE_VAL), "r"(val_8) 47 | ); 48 | assert(*val_8 == 1); 49 | 50 | free(val_8); 51 | } 52 | 53 | void test_halfword() { 54 | uint32_t *val_32 = (uint32_t *)malloc(sizeof(uint32_t)); 55 | *val_32 = START_VAL; 56 | asm ( 57 | "mov w3, %0\n\t" 58 | "mov x4, %1\n\t" 59 | "steorh w3,[x4]\n\t" 60 | :: "I"(CHANGE_VAL), "r"(val_32) 61 | ); 62 | assert(*val_32 == 0); 63 | 64 | asm ( 65 | "mov w3, %0\n\t" 66 | "mov x4, %1\n\t" 67 | "steorlh w3,[x4]\n\t" 68 | :: "I"(CHANGE_VAL), "r"(val_32) 69 | ); 70 | assert(*val_32 == 1); 71 | 72 | free(val_32); 73 | } 74 | 75 | int main() { 76 | test_standard(); 77 | test_byte(); 78 | test_halfword(); 79 | fprintf(stderr, "%s\n", "Test passed."); 80 | return 0; 81 | } 82 | -------------------------------------------------------------------------------- /test/arm_insts/v8.1/STLLRx.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define FIRST_VAL 42 7 | 8 | void test_standard() { 9 | uint64_t *result_64 = (uint64_t *)malloc(sizeof(uint64_t)); 10 | *result_64 = 0; 11 | asm ( 12 | "mov x4, %0\n\t" 13 | "mov x3, %1\n\t" 14 | "stllr x3,[x4]\n\t" 15 | :: "r"(result_64), "I"(FIRST_VAL) 16 | ); 17 | assert(*result_64 == FIRST_VAL); 18 | 19 | free(result_64); 20 | } 21 | 22 | void test_byte() { 23 | uint8_t *result_8 = (uint8_t *)malloc(sizeof(uint8_t)); 24 | *result_8 = 0; 25 | asm ( 26 | "mov x4, %0\n\t" 27 | "mov w3, %1\n\t" 28 | "stllrb w3,[x4]\n\t" 29 | :: "r"(result_8), "I"(FIRST_VAL) 30 | ); 31 | assert(*result_8 == FIRST_VAL); 32 | 33 | free(result_8); 34 | } 35 | 36 | void test_halfword() { 37 | uint32_t *result_32 = (uint32_t *)malloc(sizeof(uint32_t)); 38 | *result_32 = 0; 39 | asm ( 40 | "mov x4, %0\n\t" 41 | "mov w3, %1\n\t" 42 | "stllrh w3,[x4]\n\t" 43 | :: "r"(result_32), "I"(FIRST_VAL) 44 | ); 45 | assert(*result_32 == FIRST_VAL); 46 | 47 | free(result_32); 48 | } 49 | 50 | int main() { 51 | test_standard(); 52 | test_byte(); 53 | test_halfword(); 54 | fprintf(stderr, "%s\n", "Test passed."); 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /test/arm_insts/v8.1/STSETx.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define START_VAL 1 7 | #define CHANGE_VAL 1 8 | 9 | void test_standard() { 10 | uint64_t *val_64 = (uint64_t *)malloc(sizeof(uint64_t)); 11 | *val_64 = START_VAL; 12 | asm ( 13 | "mov x3, %0\n\t" 14 | "mov x4, %1\n\t" 15 | "stset x3,[x4]\n\t" 16 | :: "I"(CHANGE_VAL), "r"(val_64) 17 | ); 18 | assert(*val_64 == 1); 19 | 20 | asm ( 21 | "mov x3, %0\n\t" 22 | "mov x4, %1\n\t" 23 | "stsetl x3,[x4]\n\t" 24 | :: "I"(CHANGE_VAL), "r"(val_64) 25 | ); 26 | assert(*val_64 == 1); 27 | 28 | free(val_64); 29 | } 30 | 31 | void test_byte() { 32 | uint8_t *val_8 = (uint8_t *)malloc(sizeof(uint8_t)); 33 | *val_8 = START_VAL; 34 | asm ( 35 | "mov w3, %0\n\t" 36 | "mov x4, %1\n\t" 37 | "stsetb w3,[x4]\n\t" 38 | :: "I"(CHANGE_VAL), "r"(val_8) 39 | ); 40 | assert(*val_8 == 1); 41 | 42 | asm ( 43 | "mov w3, %0\n\t" 44 | "mov x4, %1\n\t" 45 | "stsetlb w3,[x4]\n\t" 46 | :: "I"(CHANGE_VAL), "r"(val_8) 47 | ); 48 | assert(*val_8 == 1); 49 | 50 | free(val_8); 51 | } 52 | 53 | void test_halfword() { 54 | uint32_t *val_32 = (uint32_t *)malloc(sizeof(uint32_t)); 55 | *val_32 = START_VAL; 56 | asm ( 57 | "mov w3, %0\n\t" 58 | "mov x4, %1\n\t" 59 | "stseth w3,[x4]\n\t" 60 | :: "I"(CHANGE_VAL), "r"(val_32) 61 | ); 62 | assert(*val_32 == 1); 63 | 64 | asm ( 65 | "mov w3, %0\n\t" 66 | "mov x4, %1\n\t" 67 | "stsetlh w3,[x4]\n\t" 68 | :: "I"(CHANGE_VAL), "r"(val_32) 69 | ); 70 | assert(*val_32 == 1); 71 | 72 | free(val_32); 73 | } 74 | 75 | int main() { 76 | test_standard(); 77 | test_byte(); 78 | test_halfword(); 79 | fprintf(stderr, "%s\n", "Test passed."); 80 | return 0; 81 | } 82 | -------------------------------------------------------------------------------- /test/arm_insts/v8.1/STSMAXx.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define FIRST_VAL 42 7 | #define SECOND_VAL 43 8 | 9 | void test_standard() { 10 | uint64_t *val_64 = (uint64_t *)malloc(sizeof(uint64_t)); 11 | *val_64 = FIRST_VAL; 12 | asm ( 13 | "mov x3, %0\n\t" 14 | "mov x4, %1\n\t" 15 | "stsmax x3,[x4]\n\t" 16 | :: "I"(SECOND_VAL), "r"(val_64) 17 | ); 18 | assert(*val_64 == SECOND_VAL); 19 | 20 | asm ( 21 | "mov x3, %0\n\t" 22 | "mov x4, %1\n\t" 23 | "stsmaxl x3,[x4]\n\t" 24 | :: "I"(SECOND_VAL+1), "r"(val_64) 25 | ); 26 | assert(*val_64 == SECOND_VAL+1); 27 | 28 | free(val_64); 29 | } 30 | 31 | void test_byte() { 32 | uint8_t *val_8 = (uint8_t *)malloc(sizeof(uint8_t)); 33 | *val_8 = FIRST_VAL; 34 | asm ( 35 | "mov w3, %0\n\t" 36 | "mov x4, %1\n\t" 37 | "stsmaxb w3,[x4]\n\t" 38 | :: "I"(SECOND_VAL), "r"(val_8) 39 | ); 40 | assert(*val_8 == SECOND_VAL); 41 | 42 | asm ( 43 | "mov w3, %0\n\t" 44 | "mov x4, %1\n\t" 45 | "stsmaxlb w3,[x4]\n\t" 46 | :: "I"(SECOND_VAL+1), "r"(val_8) 47 | ); 48 | assert(*val_8 == SECOND_VAL+1); 49 | 50 | free(val_8); 51 | } 52 | 53 | void test_halfword() { 54 | uint32_t *val_32 = (uint32_t *)malloc(sizeof(uint32_t)); 55 | *val_32 = FIRST_VAL; 56 | asm ( 57 | "mov w3, %0\n\t" 58 | "mov x4, %1\n\t" 59 | "stsmaxh w3,[x4]\n\t" 60 | :: "I"(SECOND_VAL), "r"(val_32) 61 | ); 62 | assert(*val_32 == SECOND_VAL); 63 | 64 | asm ( 65 | "mov w3, %0\n\t" 66 | "mov x4, %1\n\t" 67 | "stsmaxlh w3,[x4]\n\t" 68 | :: "I"(SECOND_VAL+1), "r"(val_32) 69 | ); 70 | assert(*val_32 == SECOND_VAL+1); 71 | 72 | free(val_32); 73 | } 74 | 75 | int main() { 76 | test_standard(); 77 | test_byte(); 78 | test_halfword(); 79 | fprintf(stderr, "%s\n", "Test passed."); 80 | return 0; 81 | } 82 | -------------------------------------------------------------------------------- /test/arm_insts/v8.1/STSMINx.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define FIRST_VAL 42 7 | #define SECOND_VAL 41 8 | 9 | void test_standard() { 10 | uint64_t *val_64 = (uint64_t *)malloc(sizeof(uint64_t)); 11 | *val_64 = FIRST_VAL; 12 | asm ( 13 | "mov x3, %0\n\t" 14 | "mov x4, %1\n\t" 15 | "stsmin x3,[x4]\n\t" 16 | :: "I"(SECOND_VAL), "r"(val_64) 17 | ); 18 | assert(*val_64 == SECOND_VAL); 19 | 20 | asm ( 21 | "mov x3, %0\n\t" 22 | "mov x4, %1\n\t" 23 | "stsminl x3,[x4]\n\t" 24 | :: "I"(SECOND_VAL-1), "r"(val_64) 25 | ); 26 | assert(*val_64 == SECOND_VAL-1); 27 | 28 | free(val_64); 29 | } 30 | 31 | void test_byte() { 32 | uint8_t *val_8 = (uint8_t *)malloc(sizeof(uint8_t)); 33 | *val_8 = FIRST_VAL; 34 | asm ( 35 | "mov w3, %0\n\t" 36 | "mov x4, %1\n\t" 37 | "stsminb w3,[x4]\n\t" 38 | :: "I"(SECOND_VAL), "r"(val_8) 39 | ); 40 | assert(*val_8 == SECOND_VAL); 41 | 42 | asm ( 43 | "mov w3, %0\n\t" 44 | "mov x4, %1\n\t" 45 | "stsminlb w3,[x4]\n\t" 46 | :: "I"(SECOND_VAL-1), "r"(val_8) 47 | ); 48 | assert(*val_8 == SECOND_VAL-1); 49 | 50 | free(val_8); 51 | } 52 | 53 | void test_halfword() { 54 | uint32_t *val_32 = (uint32_t *)malloc(sizeof(uint32_t)); 55 | *val_32 = FIRST_VAL; 56 | asm ( 57 | "mov w3, %0\n\t" 58 | "mov x4, %1\n\t" 59 | "stsminh w3,[x4]\n\t" 60 | :: "I"(SECOND_VAL), "r"(val_32) 61 | ); 62 | assert(*val_32 == SECOND_VAL); 63 | 64 | asm ( 65 | "mov w3, %0\n\t" 66 | "mov x4, %1\n\t" 67 | "stsminlh w3,[x4]\n\t" 68 | :: "I"(SECOND_VAL-1), "r"(val_32) 69 | ); 70 | assert(*val_32 == SECOND_VAL-1); 71 | 72 | free(val_32); 73 | } 74 | 75 | int main() { 76 | test_standard(); 77 | test_byte(); 78 | test_halfword(); 79 | fprintf(stderr, "%s\n", "Test passed."); 80 | return 0; 81 | } 82 | -------------------------------------------------------------------------------- /test/arm_insts/v8.1/STUMAXx.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define FIRST_VAL 42 7 | #define SECOND_VAL 43 8 | 9 | void test_standard() { 10 | uint64_t *val_64 = (uint64_t *)malloc(sizeof(uint64_t)); 11 | *val_64 = FIRST_VAL; 12 | asm ( 13 | "mov x3, %0\n\t" 14 | "mov x4, %1\n\t" 15 | "stumax x3,[x4]\n\t" 16 | :: "I"(SECOND_VAL), "r"(val_64) 17 | ); 18 | assert(*val_64 == SECOND_VAL); 19 | 20 | asm ( 21 | "mov x3, %0\n\t" 22 | "mov x4, %1\n\t" 23 | "stumaxl x3,[x4]\n\t" 24 | :: "I"(SECOND_VAL+1), "r"(val_64) 25 | ); 26 | assert(*val_64 == SECOND_VAL+1); 27 | 28 | free(val_64); 29 | } 30 | 31 | void test_byte() { 32 | uint8_t *val_8 = (uint8_t *)malloc(sizeof(uint8_t)); 33 | *val_8 = FIRST_VAL; 34 | asm ( 35 | "mov w3, %0\n\t" 36 | "mov x4, %1\n\t" 37 | "stumaxb w3,[x4]\n\t" 38 | :: "I"(SECOND_VAL), "r"(val_8) 39 | ); 40 | assert(*val_8 == SECOND_VAL); 41 | 42 | asm ( 43 | "mov w3, %0\n\t" 44 | "mov x4, %1\n\t" 45 | "stumaxlb w3,[x4]\n\t" 46 | :: "I"(SECOND_VAL+1), "r"(val_8) 47 | ); 48 | assert(*val_8 == SECOND_VAL+1); 49 | 50 | free(val_8); 51 | } 52 | 53 | void test_halfword() { 54 | uint32_t *val_32 = (uint32_t *)malloc(sizeof(uint32_t)); 55 | *val_32 = FIRST_VAL; 56 | asm ( 57 | "mov w3, %0\n\t" 58 | "mov x4, %1\n\t" 59 | "stumaxh w3,[x4]\n\t" 60 | :: "I"(SECOND_VAL), "r"(val_32) 61 | ); 62 | assert(*val_32 == SECOND_VAL); 63 | 64 | asm ( 65 | "mov w3, %0\n\t" 66 | "mov x4, %1\n\t" 67 | "stumaxlh w3,[x4]\n\t" 68 | :: "I"(SECOND_VAL+1), "r"(val_32) 69 | ); 70 | assert(*val_32 == SECOND_VAL+1); 71 | 72 | free(val_32); 73 | } 74 | 75 | int main() { 76 | test_standard(); 77 | test_byte(); 78 | test_halfword(); 79 | fprintf(stderr, "%s\n", "Test passed."); 80 | return 0; 81 | } 82 | -------------------------------------------------------------------------------- /test/arm_insts/v8.1/STUMINx.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define FIRST_VAL 42 7 | #define SECOND_VAL 41 8 | 9 | void test_standard() { 10 | uint64_t *val_64 = (uint64_t *)malloc(sizeof(uint64_t)); 11 | *val_64 = FIRST_VAL; 12 | asm ( 13 | "mov x3, %0\n\t" 14 | "mov x4, %1\n\t" 15 | "stumin x3,[x4]\n\t" 16 | :: "I"(SECOND_VAL), "r"(val_64) 17 | ); 18 | assert(*val_64 == SECOND_VAL); 19 | 20 | asm ( 21 | "mov x3, %0\n\t" 22 | "mov x4, %1\n\t" 23 | "stuminl x3,[x4]\n\t" 24 | :: "I"(SECOND_VAL-1), "r"(val_64) 25 | ); 26 | assert(*val_64 == SECOND_VAL-1); 27 | 28 | free(val_64); 29 | } 30 | 31 | void test_byte() { 32 | uint8_t *val_8 = (uint8_t *)malloc(sizeof(uint8_t)); 33 | *val_8 = FIRST_VAL; 34 | asm ( 35 | "mov w3, %0\n\t" 36 | "mov x4, %1\n\t" 37 | "stuminb w3,[x4]\n\t" 38 | :: "I"(SECOND_VAL), "r"(val_8) 39 | ); 40 | assert(*val_8 == SECOND_VAL); 41 | 42 | asm ( 43 | "mov w3, %0\n\t" 44 | "mov x4, %1\n\t" 45 | "stuminlb w3,[x4]\n\t" 46 | :: "I"(SECOND_VAL-1), "r"(val_8) 47 | ); 48 | assert(*val_8 == SECOND_VAL-1); 49 | 50 | free(val_8); 51 | } 52 | 53 | void test_halfword() { 54 | uint32_t *val_32 = (uint32_t *)malloc(sizeof(uint32_t)); 55 | *val_32 = FIRST_VAL; 56 | asm ( 57 | "mov w3, %0\n\t" 58 | "mov x4, %1\n\t" 59 | "stuminh w3,[x4]\n\t" 60 | :: "I"(SECOND_VAL), "r"(val_32) 61 | ); 62 | assert(*val_32 == SECOND_VAL); 63 | 64 | asm ( 65 | "mov w3, %0\n\t" 66 | "mov x4, %1\n\t" 67 | "stuminlh w3,[x4]\n\t" 68 | :: "I"(SECOND_VAL-1), "r"(val_32) 69 | ); 70 | assert(*val_32 == SECOND_VAL-1); 71 | 72 | free(val_32); 73 | } 74 | 75 | int main() { 76 | test_standard(); 77 | test_byte(); 78 | test_halfword(); 79 | fprintf(stderr, "%s\n", "Test passed."); 80 | return 0; 81 | } 82 | -------------------------------------------------------------------------------- /test/arm_insts/v8.1/SWPx.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define FIRST_VAL 42 7 | #define SECOND_VAL 43 8 | 9 | void test_standard() { 10 | uint64_t *val_64 = (uint64_t *)malloc(sizeof(uint64_t)); 11 | *val_64 = FIRST_VAL; 12 | asm ( 13 | "mov x3, %0\n\t" 14 | "mov x4, %1\n\t" 15 | "swp x3,x3,[x4]\n\t" 16 | :: "I"(SECOND_VAL), "r"(val_64) 17 | ); 18 | assert(*val_64 == SECOND_VAL); 19 | 20 | asm ( 21 | "mov x3, %0\n\t" 22 | "mov x4, %1\n\t" 23 | "swpa x3,x3,[x4]\n\t" 24 | :: "I"(SECOND_VAL+1), "r"(val_64) 25 | ); 26 | assert(*val_64 == SECOND_VAL+1); 27 | 28 | asm ( 29 | "mov x3, %0\n\t" 30 | "mov x4, %1\n\t" 31 | "swpal x3,x3,[x4]\n\t" 32 | :: "I"(SECOND_VAL+2), "r"(val_64) 33 | ); 34 | assert(*val_64 == SECOND_VAL+2); 35 | 36 | asm ( 37 | "mov x3, %0\n\t" 38 | "mov x4, %1\n\t" 39 | "swpl x3,x3,[x4]\n\t" 40 | :: "I"(SECOND_VAL+3), "r"(val_64) 41 | ); 42 | assert(*val_64 == SECOND_VAL+3); 43 | 44 | free(val_64); 45 | } 46 | 47 | void test_byte() { 48 | uint8_t *val_8 = (uint8_t *)malloc(sizeof(uint8_t)); 49 | *val_8 = FIRST_VAL; 50 | asm ( 51 | "mov w3, %0\n\t" 52 | "mov x4, %1\n\t" 53 | "swpb w3,w3,[x4]\n\t" 54 | :: "I"(SECOND_VAL), "r"(val_8) 55 | ); 56 | assert(*val_8 == SECOND_VAL); 57 | 58 | asm ( 59 | "mov w3, %0\n\t" 60 | "mov x4, %1\n\t" 61 | "swpab w3,w3,[x4]\n\t" 62 | :: "I"(SECOND_VAL+1), "r"(val_8) 63 | ); 64 | assert(*val_8 == SECOND_VAL+1); 65 | 66 | asm ( 67 | "mov w3, %0\n\t" 68 | "mov x4, %1\n\t" 69 | "swpalb w3,w3,[x4]\n\t" 70 | :: "I"(SECOND_VAL+2), "r"(val_8) 71 | ); 72 | assert(*val_8 == SECOND_VAL+2); 73 | 74 | asm ( 75 | "mov w3, %0\n\t" 76 | "mov x4, %1\n\t" 77 | "swplb w3,w3,[x4]\n\t" 78 | :: "I"(SECOND_VAL+3), "r"(val_8) 79 | ); 80 | assert(*val_8 == SECOND_VAL+3); 81 | 82 | free(val_8); 83 | } 84 | 85 | void test_halfword() { 86 | uint32_t *val_32 = (uint32_t *)malloc(sizeof(uint32_t)); 87 | *val_32 = FIRST_VAL; 88 | asm ( 89 | "mov w3, %0\n\t" 90 | "mov x4, %1\n\t" 91 | "swph w3,w3,[x4]\n\t" 92 | :: "I"(SECOND_VAL), "r"(val_32) 93 | ); 94 | assert(*val_32 == SECOND_VAL); 95 | 96 | asm ( 97 | "mov w3, %0\n\t" 98 | "mov x4, %1\n\t" 99 | "swpah w3,w3,[x4]\n\t" 100 | :: "I"(SECOND_VAL+1), "r"(val_32) 101 | ); 102 | assert(*val_32 == SECOND_VAL+1); 103 | 104 | asm ( 105 | "mov w3, %0\n\t" 106 | "mov x4, %1\n\t" 107 | "swpalh w3,w3,[x4]\n\t" 108 | :: "I"(SECOND_VAL+2), "r"(val_32) 109 | ); 110 | assert(*val_32 == SECOND_VAL+2); 111 | 112 | asm ( 113 | "mov w3, %0\n\t" 114 | "mov x4, %1\n\t" 115 | "swplh w3,w3,[x4]\n\t" 116 | :: "I"(SECOND_VAL+3), "r"(val_32) 117 | ); 118 | assert(*val_32 == SECOND_VAL+3); 119 | 120 | free(val_32); 121 | } 122 | 123 | int main() { 124 | test_standard(); 125 | test_byte(); 126 | test_halfword(); 127 | fprintf(stderr, "%s\n", "Test passed."); 128 | return 0; 129 | } 130 | -------------------------------------------------------------------------------- /test/arm_insts/v8.1/VQRDMLAH.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void test_standard() { 7 | asm ( 8 | "VQRDMLAH.s32 q0,q1,q2\n\t" 9 | ); 10 | 11 | asm ( 12 | "VQRDMLSH.s32 q0,q1,q2\n\t" 13 | ); 14 | 15 | // asm ( 16 | // "movi v0.8b,3\n\t" 17 | // "movi v1.8b,3\n\t" 18 | // "movi v2.8b,3\n\t" 19 | // "vqrdmlah h0,h1,v2.h[1]\n\t" 20 | // ); 21 | } 22 | 23 | int main() { 24 | test_standard(); 25 | fprintf(stderr, "%s\n", "Test passed."); 26 | return 0; 27 | } -------------------------------------------------------------------------------- /test/arm_insts/v8.1/makefile: -------------------------------------------------------------------------------- 1 | CFLAGS=-march=armv8.2-a 2 | ARCH=$(shell $(CC) -dumpmachine | awk -F '-' '{print $$1}') 3 | 4 | ifeq ($(ARCH),aarch64) 5 | aarch64: CASPx CASx LDADDx LDCLRx LDEORx LDLARx LDSETx LDSMAXx LDSMINx LDUMAXx LDUMINx SQRDMLxH STADDx STCLRx STEORx STLLRx STSETx STSMAXx STSMINx STUMAXx STUMINx SWPx 6 | else ifeq ($(findstring arm, $(ARCH)), arm) 7 | CFLAGS+=-mthumb -mfpu=neon-fp-armv8 8 | aarch32: VQRDMLAH 9 | else 10 | fallback: $(error $(ARCH) isn't supported) 11 | endif 12 | 13 | clean: 14 | rm -f CASPx CASx LDADDx LDCLRx LDEORx LDLARx LDSETx LDSMAXx LDSMINx LDUMAXx LDUMINx SQRDMLxH STADDx STCLRx STEORx STLLRx STSETx STSMAXx STSMINx STUMAXx STUMINx SWPx VQRDMLAH 15 | -------------------------------------------------------------------------------- /test/arm_insts/v8.2/ATS1E1RP.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void test_standard() { 7 | 8 | asm ( 9 | "AT S1E1RP, x3\n\t" 10 | ); 11 | } 12 | 13 | int main() { 14 | test_standard(); 15 | fprintf(stderr, "%s\n", "Test passed."); 16 | return 0; 17 | } -------------------------------------------------------------------------------- /test/arm_insts/v8.2/ATS1E1WP.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void test_standard() { 7 | 8 | asm ( 9 | "AT S1E1WP, x3\n\t" 10 | ); 11 | } 12 | 13 | int main() { 14 | test_standard(); 15 | fprintf(stderr, "%s\n", "Test passed."); 16 | return 0; 17 | } -------------------------------------------------------------------------------- /test/arm_insts/v8.2/BFC.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define FIRST_VAL_32 0 7 | #define SECOND_VAL_32 32 8 | #define FIRST_VAL_64 0 9 | #define SECOND_VAL_64 64 10 | 11 | void test_standard() { 12 | 13 | asm ( 14 | "bfc w3,%0,%1\n\t" 15 | "bfc x3,%2,%3\n\t" 16 | :: "I"(FIRST_VAL_32), "I"(SECOND_VAL_32), "I"(FIRST_VAL_64), "I"(SECOND_VAL_64) 17 | ); 18 | } 19 | 20 | int main() { 21 | test_standard(); 22 | fprintf(stderr, "%s\n", "Test passed."); 23 | return 0; 24 | } -------------------------------------------------------------------------------- /test/arm_insts/v8.2/CRYPTO.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void test_standard() { 7 | 8 | asm ( 9 | "sha512h q2,q1,v2.2d\n\t" 10 | "sha512h2 q2,q1,v2.2d\n\t" 11 | "sha512su0 v2.2d,v1.2d\n\t" 12 | "sha512su1 v2.2d,v1.2d,v0.2d\n\t" 13 | "bcax z3.d,z3.d,z2.d,z1.d\n\t" 14 | "eor3 z3.d,z3.d,z2.d,z1.d\n\t" 15 | "rax1 v3.2d,v2.2d,v1.2d\n\t" 16 | "xar z3.d,z3.d,z2.d,#1\n\t" 17 | "sm3ss1 v3.4s,v2.4s,v1.4s,v0.4s\n\t" 18 | "sm3tt1a v3.4s,v2.4s,v1.s[0]\n\t" 19 | "sm3tt1b v3.4s,v2.4s,v1.s[0]\n\t" 20 | "sm3tt2a v3.4s,v2.4s,v1.s[0]\n\t" 21 | "sm3tt2b v3.4s,v2.4s,v1.s[0]\n\t" 22 | "sm3partw1 v3.4s,v2.4s,v1.4s\n\t" 23 | "sm3partw2 v3.4s,v2.4s,v1.4s\n\t" 24 | "sm4e v3.4s,v2.4s\n\t" 25 | "sm4ekey v3.4s,v2.4s,v1.4s\n\t" 26 | ); 27 | } 28 | 29 | int main() { 30 | test_standard(); 31 | fprintf(stderr, "%s\n", "Test passed."); 32 | return 0; 33 | } -------------------------------------------------------------------------------- /test/arm_insts/v8.2/DCCVAP.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void test_standard() { 7 | 8 | asm ( 9 | "DC CVAP, x3\n\t" 10 | ); 11 | } 12 | 13 | int main() { 14 | test_standard(); 15 | fprintf(stderr, "%s\n", "Test passed."); 16 | return 0; 17 | } -------------------------------------------------------------------------------- /test/arm_insts/v8.2/FEAT_FHM_64.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void test_standard() { 7 | 8 | asm ( 9 | "fmlal v3.2s,v2.2h,v1.h[0]\n\t" 10 | "fmlal2 v3.2s,v2.2h,v1.h[0]\n\t" 11 | "fmlal v3.2s,v2.2h,v1.2h\n\t" 12 | "fmlal2 v3.2s,v2.2h,v1.2h\n\t" 13 | "fmlsl v3.2s,v2.2h,v1.h[0]\n\t" 14 | "fmlsl2 v3.2s,v2.2h,v1.h[0]\n\t" 15 | "fmlsl v3.2s,v2.2h,v1.2h\n\t" 16 | "fmlsl2 v3.2s,v2.2h,v1.2h\n\t" 17 | ); 18 | } 19 | 20 | int main() { 21 | test_standard(); 22 | fprintf(stderr, "%s\n", "Test passed."); 23 | return 0; 24 | } -------------------------------------------------------------------------------- /test/arm_insts/v8.2/FEAT_FP16_64.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void test_standard() { 7 | 8 | asm ( 9 | "fabd h3,h2,h1\n\t" 10 | "fabd v2.4h,v1.4h,v0.4h\n\t" 11 | "fabs v2.4h,v1.4h\n\t" 12 | "facge h3,h2,h1\n\t" 13 | "facge v3.4h,v2.4h,v1.4h\n\t" 14 | "facgt h3,h2,h1\n\t" 15 | "facgt v3.4h,v2.4h,v1.4h\n\t" 16 | "fadd v3.4h,v2.4h,v1.4h\n\t" 17 | "faddp h2,v2.2h\n\t" 18 | "faddp v3.4h,v2.4h,v1.4h\n\t" 19 | "fcmeq h3,h2,h1\n\t" 20 | "fcmeq v3.4h,v2.4h,v1.4h\n\t" 21 | "fcmeq h3,h2,#0.0\n\t" 22 | "fcmeq v3.4h,v2.4h,#0.0\n\t" 23 | "fcmge h3,h2,h1\n\t" 24 | "fcmge v3.4h,v2.4h,v1.4h\n\t" 25 | "fcmge h3,h2,#0.0\n\t" 26 | "fcmge v3.4h,v2.4h,#0.0\n\t" 27 | "fcmgt h3,h2,h1\n\t" 28 | "fcmgt v3.4h,v2.4h,v1.4h\n\t" 29 | "fcmgt h3,h2,#0.0\n\t" 30 | "fcmgt v3.4h,v2.4h,#0.0\n\t" 31 | "fcmle h3,h2,#0.0\n\t" 32 | "fcmle v3.4h,v2.4h,#0.0\n\t" 33 | "fcmlt h3,h2,#0.0\n\t" 34 | "fcmlt v3.4h,v2.4h,#0.0\n\t" 35 | "fcvtas h3,h2\n\t" 36 | "fcvtas v3.4h,v2.4h\n\t" 37 | "fcvtau h3,h2\n\t" 38 | "fcvtau v3.4h,v2.4h\n\t" 39 | "fcvtms h3,h2\n\t" 40 | "fcvtms v3.4h,v2.4h\n\t" 41 | "fcvtmu h3,h2\n\t" 42 | "fcvtmu v3.4h,v2.4h\n\t" 43 | "fcvtns h3,h2\n\t" 44 | "fcvtns v3.4h,v2.4h\n\t" 45 | "fcvtnu h3,h2\n\t" 46 | "fcvtnu v3.4h,v2.4h\n\t" 47 | "fcvtps h3,h2\n\t" 48 | "fcvtps v3.4h,v2.4h\n\t" 49 | "fcvtpu h3,h2\n\t" 50 | "fcvtpu v3.4h,v2.4h\n\t" 51 | "fcvtzs h3,h2\n\t" 52 | "fcvtzs v3.4h,v2.4h\n\t" 53 | "fcvtzu h3,h2\n\t" 54 | "fcvtzu v3.4h,v2.4h\n\t" 55 | "fdiv v3.4h,v2.4h,v1.4h\n\t" 56 | "fmax v3.4h,v2.4h,v1.4h\n\t" 57 | "fmaxnm v3.4h,v2.4h,v1.4h\n\t" 58 | "fmaxnmp h2,v2.2h\n\t" 59 | "fmaxnmp v3.4h,v2.4h,v1.4h\n\t" 60 | "fmaxnmv h2,v2.4h\n\t" 61 | "fmaxp h2,v2.2h\n\t" 62 | "fmaxp v3.4h,v2.4h,v1.4h\n\t" 63 | "fmaxv h2,v2.4h\n\t" 64 | "fmin v3.4h,v2.4h,v1.4h\n\t" 65 | "fminnm v3.4h,v2.4h,v1.4h\n\t" 66 | "fminnmp h2,v2.2h\n\t" 67 | "fminnmp v3.4h,v2.4h,v1.4h\n\t" 68 | "fminnmv h2,v2.4h\n\t" 69 | "fminp h2,v2.2h\n\t" 70 | "fminp v3.4h,v2.4h,v1.4h\n\t" 71 | "fminv h2,v2.4h\n\t" 72 | "fmla h2,h1,v1.h[0]\n\t" 73 | "fmla v3.4h,v2.4h,v1.h[0]\n\t" 74 | "fmla v3.4h,v2.4h,v1.4h\n\t" 75 | "fmls h2,h1,v1.h[0]\n\t" 76 | "fmls v3.4h,v2.4h,v1.h[0]\n\t" 77 | "fmls v3.4h,v2.4h,v1.4h\n\t" 78 | "fmov v3.4h,#02\n\t" 79 | "fmul h2,h1,v1.h[0]\n\t" 80 | "fmul v3.4h,v2.4h,v1.h[0]\n\t" 81 | "fmul v3.4h,v2.4h,v1.4h\n\t" 82 | "fmulx h2,h1,v1.h[0]\n\t" 83 | "fmulx v3.4h,v2.4h,v1.h[0]\n\t" 84 | "fmulx v3.4h,v2.4h,v1.4h\n\t" 85 | "fmulx h3,h2,h1\n\t" 86 | "fneg v3.4h,v2.4h\n\t" 87 | "frecpe h3,h2\n\t" 88 | "frecpe v3.4h,v2.4h\n\t" 89 | "frecps h3,h2,h1\n\t" 90 | "frecps v3.4h,v2.4h,v1.4h\n\t" 91 | "frecpx h3,h2\n\t" 92 | "frinta v3.4h,v2.4h\n\t" 93 | "frinti v3.4h,v2.4h\n\t" 94 | "frintm v3.4h,v2.4h\n\t" 95 | "frintn v3.4h,v2.4h\n\t" 96 | "frintp v3.4h,v2.4h\n\t" 97 | "frintx v3.4h,v2.4h\n\t" 98 | "frintz v3.4h,v2.4h\n\t" 99 | "frsqrte v3.4h,v2.4h\n\t" 100 | "frsqrte h3,h2\n\t" 101 | "frsqrts v3.4h,v2.4h,v1.4h\n\t" 102 | "frsqrts h3,h2,h1\n\t" 103 | "fsqrt v3.4h,v2.4h\n\t" 104 | "fsub v3.4h,v2.4h,v1.4h\n\t" 105 | "scvtf h3,h2\n\t" 106 | "scvtf v3.4h,v2.4h\n\t" 107 | "ucvtf h3,h2\n\t" 108 | "ucvtf v3.4h,v2.4h\n\t" 109 | ); 110 | } 111 | 112 | int main() { 113 | test_standard(); 114 | fprintf(stderr, "%s\n", "Test passed."); 115 | return 0; 116 | } -------------------------------------------------------------------------------- /test/arm_insts/v8.2/FMMLA.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void test_standard() { 7 | 8 | asm ( 9 | "fmmla z3.s,z2.s,z1.s\n\t" 10 | "fmmla z3.d,z2.d,z1.d\n\t" 11 | ); 12 | } 13 | 14 | int main() { 15 | test_standard(); 16 | fprintf(stderr, "%s\n", "Test passed."); 17 | return 0; 18 | } -------------------------------------------------------------------------------- /test/arm_insts/v8.2/LD1ROx.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void test_standard() { 7 | 8 | asm ( 9 | "ld1rob z1.b,p1,[x3,#0]\n\t" 10 | "ld1rob z1.b,p1,[x3,x2]\n\t" 11 | "ld1roh z1.h,p1,[x3,#0]\n\t" 12 | "ld1roh z1.h,p1,[x3,x2,lsl #1]\n\t" 13 | "ld1row z1.s,p1,[x3,#0]\n\t" 14 | "ld1row z1.s,p1,[x3,x2,lsl #2]\n\t" 15 | "ld1rod z1.d,p1,[x3,#0]\n\t" 16 | "ld1rod z1.d,p1,[x3,x2,lsl #3]\n\t" 17 | ); 18 | } 19 | 20 | int main() { 21 | test_standard(); 22 | fprintf(stderr, "%s\n", "Test passed."); 23 | return 0; 24 | } -------------------------------------------------------------------------------- /test/arm_insts/v8.2/REV64.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void test_standard() { 7 | 8 | asm ( 9 | "rev64 x3, x2\n\t" 10 | ); 11 | } 12 | 13 | int main() { 14 | test_standard(); 15 | fprintf(stderr, "%s\n", "Test passed."); 16 | return 0; 17 | } -------------------------------------------------------------------------------- /test/arm_insts/v8.2/TRNx.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void test_standard() { 7 | 8 | asm ( 9 | "trn1 p2.s,p1.s,p0.s\n\t" 10 | "trn2 p2.s,p1.s,p0.s\n\t" 11 | "trn1 z2.q,z1.q,z0.q\n\t" 12 | "trn2 z2.q,z1.q,z0.q\n\t" 13 | "trn1 z2.s,z1.s,z0.s\n\t" 14 | "trn2 z2.s,z1.s,z0.s\n\t" 15 | ); 16 | } 17 | 18 | int main() { 19 | test_standard(); 20 | fprintf(stderr, "%s\n", "Test passed."); 21 | return 0; 22 | } -------------------------------------------------------------------------------- /test/arm_insts/v8.2/UZPx.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void test_standard() { 7 | 8 | asm ( 9 | "uzp1 p2.s,p1.s,p0.s\n\t" 10 | "uzp2 p2.s,p1.s,p0.s\n\t" 11 | "uzp1 z2.q,z1.q,z0.q\n\t" 12 | "uzp2 z2.q,z1.q,z0.q\n\t" 13 | "uzp1 z2.s,z1.s,z0.s\n\t" 14 | "uzp2 z2.s,z1.s,z0.s\n\t" 15 | ); 16 | } 17 | 18 | int main() { 19 | test_standard(); 20 | fprintf(stderr, "%s\n", "Test passed."); 21 | return 0; 22 | } -------------------------------------------------------------------------------- /test/arm_insts/v8.2/ZIPx.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void test_standard() { 7 | 8 | asm ( 9 | "zip1 p2.s,p1.s,p0.s\n\t" 10 | "zip2 p2.s,p1.s,p0.s\n\t" 11 | "zip1 z2.q,z1.q,z0.q\n\t" 12 | "zip2 z2.q,z1.q,z0.q\n\t" 13 | "zip1 z2.s,z1.s,z0.s\n\t" 14 | "zip2 z2.s,z1.s,z0.s\n\t" 15 | ); 16 | } 17 | 18 | int main() { 19 | test_standard(); 20 | fprintf(stderr, "%s\n", "Test passed."); 21 | return 0; 22 | } -------------------------------------------------------------------------------- /test/arm_insts/v8.2/makefile: -------------------------------------------------------------------------------- 1 | CFLAGS=-march=armv8.2-a+crypto+sha3+sm4+sve2+fp16fml+i8mm+f32mm+f64mm+dotprod 2 | 3 | all: ATS1E1RP ATS1E1WP BFC CRYPTO DCCVAP FEAT_FHM_64 FEAT_FP16_64 FMMLA LD1ROx REV64 TRNx UZPx xDOT ZIPx 4 | 5 | clean: 6 | rm -f ATS1E1RP ATS1E1WP BFC CRYPTO DCCVAP FEAT_FHM_64 FEAT_FP16_64 FMMLA LD1ROx REV64 TRNx UZPx xDOT ZIPx 7 | -------------------------------------------------------------------------------- /test/arm_insts/v8.2/xDOT.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void test_standard() { 7 | 8 | asm ( 9 | "SDOT v2.4s,v1.16b,v0.4b[0]\n\t" 10 | "SDOT v2.4s,v1.16b,v0.16b\n\t" 11 | "UDOT v2.4s,v1.16b,v0.4b[0]\n\t" 12 | "UDOT v2.4s,v1.16b,v0.16b\n\t" 13 | "USDOT v2.4s,v1.16b,v0.4b[0]\n\t" 14 | "USDOT v2.4s,v1.16b,v0.16b\n\t" 15 | "SUDOT v2.4s,v1.16b,v0.4b[0]\n\t" 16 | ); 17 | } 18 | 19 | int main() { 20 | test_standard(); 21 | fprintf(stderr, "%s\n", "Test passed."); 22 | return 0; 23 | } -------------------------------------------------------------------------------- /test/hw_div.S: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of MAMBO, a low-overhead dynamic binary modification tool: 3 | https://github.com/beehive-lab/mambo 4 | 5 | Copyright 2016 Cosmin Gorgovan 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | /* 21 | Test file for plugin instr replacement and plugins/soft_div. It should print: 22 | 23 | 827 413 1655 24 | 9478 7108 7108 25 | 4 434 1304 26 | 27 | */ 28 | 29 | .syntax unified 30 | 31 | .global main 32 | .func main 33 | .code 32 34 | main: 35 | PUSH {R4, LR} 36 | 37 | MOVW R3, #1655 38 | MOV R4, #2 39 | SDIV R1, R3, R4 40 | 41 | MOV R4, #4 42 | UDIV R2, R3, R4 43 | 44 | CMP R4, #4 45 | UDIVNE R3, R3, R4 46 | 47 | ADR R0, _tf 48 | BL printf 49 | 50 | BL div_thumb 51 | 52 | POP {R4, PC} 53 | .endfunc 54 | 55 | .global div_thumb 56 | .func div_thumb 57 | .thumb_func 58 | div_thumb: 59 | PUSH {R4, LR} 60 | 61 | ITTTT EQ 62 | NOP 63 | NOP 64 | NOP 65 | NOP 66 | 67 | MOVW R3, #28435 68 | MOV R4, #3 69 | SDIV R1, R3, R4 70 | CMP R4, #3 71 | ITTET EQ 72 | MOVEQ R4, #4 73 | UDIVEQ R2, R3, R4 74 | UDIVNE R3, R3, R4 75 | UDIVEQ R3, R3, R4 76 | LDR R0, =_tf 77 | BL printf 78 | 79 | MOVW R1, #11 80 | MOVW R2, #12 81 | MOVW R3, #1304 82 | MOVW R4, #3 83 | CMP R4, #3 84 | ITTEE EQ 85 | MOVEQ R1, #4 86 | UDIVEQ R2, R3, R4 87 | MOVNE R4, #5 88 | UDIVNE R3, R3, R4 89 | LDR R0, =_tf 90 | BL printf 91 | 92 | POP {R4, PC} 93 | .endfunc 94 | 95 | _tf: .string "%d %d %d\n" 96 | -------------------------------------------------------------------------------- /test/ihl_test.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of MAMBO, a low-overhead dynamic binary modification tool: 3 | https://github.com/beehive-lab/mambo 4 | 5 | Copyright 2022 The University of Manchester 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | #include 21 | #include 22 | 23 | #define NO_ITERATIONS 10000 24 | 25 | int main () { 26 | for (int i = 0; i < NO_ITERATIONS; i++) { 27 | int p_random_no = rand(); 28 | switch (p_random_no) 29 | { 30 | case 0: 31 | fprintf(stderr, "%s %d\n", "Equal to ", 0); 32 | break; 33 | case 1: 34 | fprintf(stderr, "%s %d\n", "Equal to ", 1); 35 | break; 36 | 37 | case 2: 38 | fprintf(stderr, "%s %d\n", "Equal to ", 2); 39 | break; 40 | 41 | case 3: 42 | fprintf(stderr, "%s %d\n", "Equal to ", 3); 43 | break; 44 | 45 | case 4: 46 | fprintf(stderr, "%s %d\n", "Equal to ", 4); 47 | break; 48 | 49 | default: 50 | fprintf(stderr, "%s\n", "No match!"); 51 | break; 52 | 53 | } 54 | } 55 | return 0; 56 | } -------------------------------------------------------------------------------- /test/makefile: -------------------------------------------------------------------------------- 1 | ARCH=$(shell $(CC) -dumpmachine | awk -F '-' '{print $$1}') 2 | ifeq ($(findstring arm, $(ARCH)), arm) 3 | PIE_ENCODER = ../pie/pie-arm-encoder.o ../pie/pie-thumb-encoder.o 4 | PIE_DECODER = ../pie/pie-arm-decoder.o ../pie/pie-thumb-decoder.o 5 | CFLAGS+=-march=armv7-a -mfpu=neon 6 | endif 7 | ifeq ($(ARCH),aarch64) 8 | PIE_ENCODER = ../pie/pie-a64-encoder.o 9 | PIE_DECODER = ../pie/pie-a64-decoder.o 10 | endif 11 | 12 | CFLAGS+=-std=gnu99 13 | LDFLAGS+=-lpthread 14 | 15 | .PHONY: clean 16 | 17 | portable: mmap_munmap mprotect_exec self_modifying signals load_store 18 | 19 | aarch32: portable hw_div 20 | 21 | aarch64: portable 22 | 23 | hw_div: hw_div.S 24 | $(CC) -mcpu=cortex-a15 $< $(LDFLAGS) -o $@ 25 | 26 | self_modifying: $(PIE_ENCODER) self_modifying.c 27 | $(CC) $(CFLAGS) $^ $(LDFLAGS) -o $@ 28 | 29 | signals: $(PIE_ENCODER) signals.c signals.S 30 | $(CC) $(CFLAGS) $^ $(LDFLAGS) -o $@ 31 | 32 | load_store: $(PIE_ENCODER) $(PIE_DECODER) load_store.c load_store.S 33 | $(CC) -g $(CFLAGS) $^ $(LDFLAGS) -o $@ 34 | 35 | clean: 36 | rm -f mmap_munmap mprotect_exec self_modifying signals hw_div load_store 37 | -------------------------------------------------------------------------------- /test/mmap_munmap.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of MAMBO, a low-overhead dynamic binary modification tool: 3 | https://github.com/beehive-lab/mambo 4 | 5 | Copyright 2017 The University of Manchester 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #define PAGESZ 4096 26 | #define BASEADDR 0x80000 27 | 28 | int main() { 29 | int ret; 30 | 31 | // Failing allocation 32 | void *alloc = mmap(NULL, 0, PROT_EXEC | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 33 | assert(alloc == MAP_FAILED); 34 | 35 | // One page allocation 36 | alloc = mmap(NULL, PAGESZ, PROT_EXEC | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 37 | assert(alloc != MAP_FAILED); 38 | 39 | ret = munmap(alloc, PAGESZ); 40 | assert (ret == 0); 41 | 42 | // Multiple page allocation, for testing partial unmapping 43 | alloc = mmap(NULL, PAGESZ*10, PROT_EXEC | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 44 | assert(alloc != MAP_FAILED); 45 | 46 | // Unmap the first page 47 | ret = munmap(alloc, PAGESZ); 48 | assert (ret == 0); 49 | alloc += PAGESZ; 50 | 51 | // Unmap the last page 52 | ret = munmap(alloc + PAGESZ*8, PAGESZ); 53 | assert (ret == 0); 54 | 55 | // Unmap the second remaining page 56 | ret = munmap(alloc + PAGESZ, PAGESZ); 57 | assert(ret == 0); 58 | 59 | // Map back the second page 60 | void *alloc2 = mmap(alloc + PAGESZ, PAGESZ, PROT_EXEC | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 61 | assert(alloc2 != MAP_FAILED); 62 | 63 | // Unmap the whole region 64 | ret = munmap(alloc, PAGESZ*8); 65 | assert(ret == 0); 66 | 67 | return 0; 68 | } 69 | -------------------------------------------------------------------------------- /test/mprotect_exec.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of MAMBO, a low-overhead dynamic binary modification tool: 3 | https://github.com/beehive-lab/mambo 4 | 5 | Copyright 2017 The University of Manchester 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #define PAGESZ 4096 27 | #define BASEADDR 0x80000 28 | 29 | int main() { 30 | int ret; 31 | 32 | printf("main()\n"); 33 | 34 | // One page allocation 35 | void *alloc = mmap((void *)BASEADDR, PAGESZ, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); 36 | assert(alloc != MAP_FAILED); 37 | 38 | // No actual change 39 | ret = mprotect(alloc, PAGESZ, PROT_READ); 40 | assert(ret == 0); 41 | 42 | // Make executable 43 | ret = mprotect(alloc, PAGESZ, PROT_READ | PROT_EXEC); 44 | assert(ret == 0); 45 | 46 | // Not executable 47 | ret = mprotect(alloc, PAGESZ, PROT_NONE); 48 | assert(ret == 0); 49 | 50 | void *large_alloc = mmap((void *)BASEADDR + PAGESZ, PAGESZ*10, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); 51 | assert(large_alloc != MAP_FAILED); 52 | 53 | // Make the first page executable 54 | ret = mprotect(alloc, PAGESZ, PROT_READ | PROT_EXEC); 55 | assert(ret == 0); 56 | 57 | // Make the third page executable 58 | ret = mprotect(alloc + PAGESZ*2, PAGESZ, PROT_READ | PROT_EXEC); 59 | assert(ret == 0); 60 | 61 | // Make the fifth page executable 62 | ret = mprotect(alloc + PAGESZ*4, PAGESZ, PROT_READ | PROT_EXEC); 63 | assert(ret == 0); 64 | 65 | // Make the first six pages executable 66 | ret = mprotect(alloc, PAGESZ*6, PROT_READ | PROT_EXEC); 67 | assert(ret == 0); 68 | 69 | // Execute-only - should fail 70 | ret = mprotect(alloc, PAGESZ, PROT_EXEC); 71 | assert(ret == 0); 72 | } 73 | -------------------------------------------------------------------------------- /test/self_modifying.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of MAMBO, a low-overhead dynamic binary modification tool: 3 | https://github.com/beehive-lab/mambo 4 | 5 | Copyright 2017 The University of Manchester 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #ifdef __arm__ 28 | #include "../pie/pie-arm-encoder.h" 29 | #elif __aarch64__ 30 | #include "../pie/pie-a64-encoder.h" 31 | #endif 32 | #include "../scanner_public.h" 33 | 34 | #define PAGESZ 4096 35 | 36 | #ifdef __arm__ 37 | #define push(reg) arm_push_reg(reg); 38 | #define pop(reg) arm_pop_reg(reg); 39 | #define reg_svc_no r7 40 | #define mov(wptr, rd, rn) arm_mov(&wptr, 0, 0, rd, rn); 41 | #define movi(wptr, rd, imm) arm_mov(&wptr, 1, 0, rd, imm); 42 | #define svc(wptr) arm_svc(&wptr, 0); 43 | #define return_inst(wptr) arm_bx(&wptr, lr); 44 | #elif __aarch64__ 45 | #define push(reg) 46 | #define pop(reg) 47 | #define r0 x0 48 | #define r1 x1 49 | #define r2 x2 50 | #define reg_svc_no x8 51 | #define mov(wptr, rd, rn) a64_logical_reg(&write_p, 1, 1, 0, 0, rn, 0, xzr, rd); 52 | #define movi(wptr, rd, imm) a64_MOV_wide(&wptr, 1, 2, 0, imm, rd); 53 | #define svc(wptr) a64_SVC (&wptr, 0); 54 | #define return_inst(wptr) a64_RET(&wptr, lr); 55 | #else 56 | #error Unknown architecture 57 | #endif 58 | 59 | typedef void (*jit_f)(char *, size_t); 60 | jit_f our_f; 61 | int ready = 0; 62 | 63 | void generate_print(uint32_t *write_p) { 64 | push(reg_svc_no); 65 | mov(write_p, r2, r1); 66 | write_p++; 67 | mov(write_p, r1, r0); 68 | write_p++; 69 | movi(write_p, r0, 1); 70 | write_p++; 71 | movi(write_p, reg_svc_no, __NR_write); 72 | write_p++; 73 | svc(write_p); 74 | write_p++; 75 | pop(reg_svc_no); 76 | return_inst(write_p); 77 | } 78 | 79 | void generate_empty(uint32_t *write_p) { 80 | return_inst(write_p); 81 | } 82 | 83 | void dispatcher(char *string) { 84 | our_f(string, strlen(string)); 85 | } 86 | 87 | void *compiler_thread(void *alloc) { 88 | generate_print(alloc); 89 | __clear_cache(alloc, alloc + PAGESZ); 90 | ready = 1; 91 | } 92 | 93 | int main() { 94 | void *alloc = mmap(NULL, PAGESZ, PROT_READ|PROT_WRITE|PROT_EXEC, 95 | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 96 | assert(alloc != MAP_FAILED); 97 | our_f = (jit_f)alloc; 98 | 99 | generate_print(alloc); 100 | __clear_cache(alloc, alloc + PAGESZ); 101 | dispatcher("This should be printed\n"); 102 | 103 | generate_empty(alloc); 104 | __clear_cache(alloc, alloc + PAGESZ); 105 | dispatcher("This shouldn't be printed\n"); 106 | 107 | pthread_t thread; 108 | pthread_create(&thread, NULL, compiler_thread, alloc); 109 | 110 | while(!ready); 111 | asm volatile("isb"); 112 | dispatcher("This should also be printed\n"); 113 | } 114 | -------------------------------------------------------------------------------- /test/signals.S: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of MAMBO, a low-overhead dynamic binary modification tool: 3 | https://github.com/beehive-lab/mambo 4 | 5 | Copyright 2017 The University of Manchester 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | #ifdef __arm__ 21 | .syntax unified 22 | #endif 23 | 24 | .global test_cbz 25 | .func 26 | 27 | #ifdef __aarch64__ 28 | test_cbz: 29 | MOV W1, #0 30 | cbz_loop: 31 | SUB W0, W0, #1 32 | AND W2, W0, #1 33 | CBZ W2, cbz_skip 34 | AND W2, W0, #2 35 | CBNZ W2, cbz_skip 36 | ADD W1, W1, #1 37 | cbz_skip: 38 | CBNZ W0, cbz_loop 39 | 40 | MOV W0, W1 41 | RET 42 | #endif 43 | 44 | #ifdef __arm__ 45 | .type test_cbz, %function 46 | .thumb_func 47 | test_cbz: 48 | MOV R1, #0 49 | cbz_loop: 50 | SUB R0, R0, #1 51 | AND R2, R0, #1 52 | CBZ R2, cbz_skip 53 | AND R2, R0, #2 54 | CBNZ R2, cbz_skip 55 | ADD R1, R1, #1 56 | cbz_skip: 57 | CMP R0, #0 58 | BNE cbz_loop 59 | 60 | MOV R0, R1 61 | BX LR 62 | #endif 63 | 64 | .endfunc 65 | 66 | #ifdef __arm__ 67 | .global test_a32_direct 68 | .func 69 | .type test_a32_direct, %function 70 | .code 32 71 | test_a32_direct: 72 | MOV R1, #0 73 | a32d_loop: 74 | SUB R0, R0, #1 75 | ANDS R2, R0, #1 76 | BEQ a32d_skip 77 | ANDS R2, R0, #2 78 | BNE a32d_skip 79 | ADD R1, R1, #1 80 | a32d_skip: 81 | CMP R0, #0 82 | BNE a32d_loop 83 | MOV R0, R1 84 | BX LR 85 | .endfunc 86 | 87 | .global test_a32_indirect 88 | .func 89 | .type test_a32_indirect, %function 90 | .code 32 91 | test_a32_indirect: 92 | MOV R1, #0 93 | a32i_loop: 94 | SUB R0, R0, #1 95 | ANDS R2, R0, #1 96 | ADREQ R2, a32i_skip 97 | ADRNE R2, a32i_cont 98 | BX R2 99 | a32i_cont: 100 | ADD R1, R1, #1 101 | a32i_skip: 102 | CMP R0, #0 103 | ADREQ R2, a32i_ret 104 | ADRNE R2, a32i_loop 105 | BX R2 106 | a32i_ret: 107 | MOV R0, R1 108 | BX LR 109 | .endfunc 110 | #endif 111 | 112 | 113 | #ifdef __aarch64__ 114 | 115 | .global test_tbz 116 | .func 117 | test_tbz: 118 | MOV W1, #0 119 | tbz_loop: 120 | SUB W0, W0, #1 121 | TBZ W0, #0, tbz_skip 122 | TBNZ W0, #1, tbz_skip 123 | ADD W1, W1, #1 124 | tbz_skip: 125 | CBNZ W0, tbz_loop 126 | 127 | MOV W0, W1 128 | RET 129 | .endfunc 130 | 131 | #endif 132 | -------------------------------------------------------------------------------- /traces_common.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of MAMBO, a low-overhead dynamic binary modification tool: 3 | https://github.com/beehive-lab/mambo 4 | Copyright 2022 The University of Manchester 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | */ 15 | 16 | #include "traces_common.h" 17 | 18 | #ifdef DBM_TRACES 19 | 20 | uintptr_t get_active_trace_spc(dbm_thread *thread_data) { 21 | int bb_id = thread_data->active_trace.source_bb; 22 | return (uintptr_t)thread_data->code_cache_meta[bb_id].source_addr; 23 | } 24 | 25 | uintptr_t active_trace_lookup_or_scan(dbm_thread *thread_data, uintptr_t target) { 26 | uintptr_t spc = get_active_trace_spc(thread_data); 27 | if (target == spc) { 28 | return adjust_cc_entry(thread_data->active_trace.entry_addr); 29 | } 30 | return lookup_or_scan(thread_data, target); 31 | } 32 | 33 | uintptr_t active_trace_lookup(dbm_thread *thread_data, uintptr_t target) { 34 | uintptr_t spc = get_active_trace_spc(thread_data); 35 | if (target == spc) { 36 | return adjust_cc_entry(thread_data->active_trace.entry_addr); 37 | } 38 | uintptr_t return_tpc = hash_lookup(&thread_data->entry_address, target); 39 | if (return_tpc >= (uintptr_t)thread_data->code_cache->traces) 40 | return adjust_cc_entry(return_tpc); 41 | return UINT_MAX; 42 | } 43 | 44 | int allocate_trace_fragment(dbm_thread *thread_data) { 45 | int id = thread_data->active_trace.id++; 46 | assert(id < (CODE_CACHE_SIZE + TRACE_FRAGMENT_NO)); 47 | return id; 48 | } 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /traces_common.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of MAMBO, a low-overhead dynamic binary modification tool: 3 | https://github.com/beehive-lab/mambo 4 | Copyright 2022 The University of Manchester 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | */ 15 | 16 | #ifndef __TRACES_COMMON_H__ 17 | #define __TRACES_COMMON_H__ 18 | 19 | #include 20 | #include 21 | #include "dbm.h" 22 | 23 | #ifdef DBM_TRACES 24 | uintptr_t get_active_trace_spc(dbm_thread *thread_data); 25 | uintptr_t active_trace_lookup_or_scan(dbm_thread *thread_data, uintptr_t target); 26 | uintptr_t active_trace_lookup(dbm_thread *thread_data, uintptr_t target); 27 | int allocate_trace_fragment(dbm_thread *thread_data); 28 | 29 | #endif 30 | #endif 31 | 32 | -------------------------------------------------------------------------------- /util.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of MAMBO, a low-overhead dynamic binary modification tool: 3 | https://github.com/beehive-lab/mambo 4 | 5 | Copyright 2013-2016 Cosmin Gorgovan 6 | Copyright 2017 The University of Manchester 7 | 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | */ 20 | 21 | #ifndef __DBM_UTIL_H__ 22 | #define __DBM_UTIL_H__ 23 | 24 | extern void dbm_client_entry(uintptr_t addr, uintptr_t *stack_top); 25 | extern uint32_t atomic_increment_u32(uint32_t *loc, uint32_t inc); 26 | extern uint64_t atomic_increment_u64(uint64_t *loc, uint64_t inc); 27 | extern int32_t atomic_decrement_if_positive_i32(int32_t *loc, int32_t inc); 28 | 29 | static inline int32_t atomic_increment_i32(int32_t *loc, int32_t inc) { 30 | return (int32_t)atomic_increment_u32((uint32_t *)loc, (uint32_t)inc); 31 | } 32 | static inline int64_t atomic_increment_i64(int64_t *loc, int64_t inc) { 33 | return (int64_t)atomic_increment_u64((uint64_t *)loc, (uint64_t)inc); 34 | } 35 | #ifdef __arm__ 36 | #define atomic_increment_uptr(loc, inc) atomic_increment_u32(loc, inc); 37 | #elif __aarch64__ 38 | #define atomic_increment_uptr(loc, inc) atomic_increment_u64(loc, inc); 39 | #endif 40 | #define atomic_increment_int(loc, inc) atomic_increment_i32(loc, inc); 41 | #define atomic_increment_uint(loc, inc) atomic_increment_u32(loc, inc); 42 | 43 | // syscall() without errno handling 44 | extern uintptr_t raw_syscall(long number, ...); 45 | void signal_trampoline(int i, siginfo_t *, void *); 46 | 47 | void safe_fcall_trampoline(); 48 | void *new_thread_trampoline(); 49 | void return_with_sp(void *sp); 50 | #endif 51 | 52 | --------------------------------------------------------------------------------