| 126 | #ifndef kNO_KEYSTONE |
| 127 | |
| 128 | MemoryPatch MemoryPatchMgr::createWithAsm(uintptr_t absolute_address, |
| 129 | MP_ASM_ARCH asm_arch, |
| 130 | const std::string &asm_code, |
| 131 | uintptr_t asm_address) |
| 132 | { |
| 133 | MemoryPatch patch; |
| 134 | |
| 135 | if (!absolute_address || asm_code.empty()) |
| 136 | return patch; |
| 137 | |
| 138 | ks_engine *ks = nullptr; |
| 139 | ks_err err = KS_ERR_ARCH; |
| 140 | |
| 141 | switch (asm_arch) |
| 142 | { |
| 143 | case MP_ASM_ARM32: |
| 144 | err = ks_open(KS_ARCH_ARM, KS_MODE_LITTLE_ENDIAN, &ks); |
| 145 | break; |
| 146 | case MP_ASM_ARM64: |
| 147 | err = ks_open(KS_ARCH_ARM64, KS_MODE_LITTLE_ENDIAN, &ks); |
| 148 | break; |
| 149 | case MP_ASM_x86: |
| 150 | err = ks_open(KS_ARCH_X86, KS_MODE_32, &ks); |
| 151 | break; |
| 152 | case MP_ASM_x86_64: |
| 153 | err = ks_open(KS_ARCH_X86, KS_MODE_64, &ks); |
| 154 | break; |
| 155 | default: |
| 156 | KITTY_LOGE("Unknown MP_ASM_ARCH '%d'.", asm_arch); |
| 157 | return patch; |
| 158 | } |
| 159 | |
| 160 | if (err != KS_ERR_OK) |
| 161 | { |
| 162 | KITTY_LOGE("ks_open failed with error = '%s'.", ks_strerror(err)); |
| 163 | return patch; |
| 164 | } |
| 165 | |
| 166 | unsigned char *insn_bytes = nullptr; |
| 167 | size_t insn_count = 0, insn_size = 0; |
| 168 | int rt = ks_asm(ks, asm_code.c_str(), asm_address, &insn_bytes, &insn_size, &insn_count); |
| 169 | |
| 170 | if (rt == 0 && insn_bytes != nullptr && insn_size) |
| 171 | { |
| 172 | patch = MemoryPatch(_pMem, absolute_address, insn_bytes, insn_size); |
| 173 | } |
| 174 | |
| 175 | if (insn_bytes != nullptr) |
| 176 | { |
| 177 | ks_free(insn_bytes); |
| 178 | } |
| 179 | |
| 180 | ks_close(ks); |
| 181 | |
| 182 | if (rt) |
| 183 | { |
| 184 | KITTY_LOGE("ks_asm failed (asm: %s, count = %zu, error = '%s') (code = %u).", |
| 185 | asm_code.c_str(), |
no test coverage detected