@@ -228,26 +228,41 @@ uint64_t A64Backend::CalculateNextHostInstruction(ThreadDebugInfo* thread_info,
228228 insn.detail = &all_detail;
229229 cs_disasm_iter (capstone_handle_, &machine_code_ptr,
230230 &remaining_machine_code_size, &host_address, &insn);
231- auto & detail = all_detail.x86 ;
231+ const auto & detail = all_detail.arm64 ;
232232 switch (insn.id ) {
233233 case ARM64_INS_B:
234- case ARM64_INS_BL:
234+ case ARM64_INS_BL: {
235+ assert_true (detail.operands [0 ].type == ARM64_OP_IMM);
236+ uint64_t target_pc = static_cast <uint64_t >(detail.operands [0 ].imm );
237+ return current_pc + target_pc;
238+ } break ;
235239 case ARM64_INS_BLR:
236- case ARM64_INS_BR:
237- case ARM64_INS_RET:
238- // todo(wunkolo): determine next instruction
239- default :
240+ case ARM64_INS_BR: {
241+ assert_true (detail.operands [0 ].type == ARM64_OP_REG);
242+ uint64_t target_pc =
243+ ReadCapstoneReg (&thread_info->host_context , detail.operands [0 ].reg );
244+ return target_pc;
245+ } break ;
246+ case ARM64_INS_RET: {
247+ assert_zero (detail.op_count );
248+ // Jump to link register
249+ return thread_info->host_context .x [30 ];
250+ } break ;
251+ case ARM64_INS_CBNZ:
252+ case ARM64_INS_CBZ:
253+ default : {
240254 // Not a branching instruction - just move over it.
241255 return current_pc + insn.size ;
256+ } break ;
242257 }
243258}
244259
245260void A64Backend::InstallBreakpoint (Breakpoint* breakpoint) {
246261 breakpoint->ForEachHostAddress ([breakpoint](uint64_t host_address) {
247262 auto ptr = reinterpret_cast <void *>(host_address);
248- auto original_bytes = xe::load_and_swap<uint16_t >(ptr);
249- assert_true (original_bytes != 0x0F0B );
250- xe::store_and_swap<uint16_t >(ptr, 0x0F0B );
263+ auto original_bytes = xe::load_and_swap<uint32_t >(ptr);
264+ assert_true (original_bytes != 0x0000'dead );
265+ xe::store_and_swap<uint32_t >(ptr, 0x0000'dead );
251266 breakpoint->backend_data ().emplace_back (host_address, original_bytes);
252267 });
253268}
@@ -265,18 +280,18 @@ void A64Backend::InstallBreakpoint(Breakpoint* breakpoint, Function* fn) {
265280
266281 // Assume we haven't already installed a breakpoint in this spot.
267282 auto ptr = reinterpret_cast <void *>(host_address);
268- auto original_bytes = xe::load_and_swap<uint16_t >(ptr);
269- assert_true (original_bytes != 0x0F0B );
270- xe::store_and_swap<uint16_t >(ptr, 0x0F0B );
283+ auto original_bytes = xe::load_and_swap<uint32_t >(ptr);
284+ assert_true (original_bytes != 0x0000'dead );
285+ xe::store_and_swap<uint32_t >(ptr, 0x0000'dead );
271286 breakpoint->backend_data ().emplace_back (host_address, original_bytes);
272287}
273288
274289void A64Backend::UninstallBreakpoint (Breakpoint* breakpoint) {
275290 for (auto & pair : breakpoint->backend_data ()) {
276291 auto ptr = reinterpret_cast <uint8_t *>(pair.first );
277- auto instruction_bytes = xe::load_and_swap<uint16_t >(ptr);
278- assert_true (instruction_bytes == 0x0F0B );
279- xe::store_and_swap<uint16_t >(ptr, static_cast <uint16_t >(pair.second ));
292+ auto instruction_bytes = xe::load_and_swap<uint32_t >(ptr);
293+ assert_true (instruction_bytes == 0x0000'dead );
294+ xe::store_and_swap<uint32_t >(ptr, static_cast <uint32_t >(pair.second ));
280295 }
281296 breakpoint->backend_data ().clear ();
282297}
@@ -296,9 +311,9 @@ bool A64Backend::ExceptionCallback(Exception* ex) {
296311
297312 // Verify an expected illegal instruction.
298313 auto instruction_bytes =
299- xe::load_and_swap<uint16_t >(reinterpret_cast <void *>(ex->pc ()));
300- if (instruction_bytes != 0x0F0B ) {
301- // Not our ud2 - not us.
314+ xe::load_and_swap<uint32_t >(reinterpret_cast <void *>(ex->pc ()));
315+ if (instruction_bytes != 0x0000'dead ) {
316+ // Not our `udf #0xdead` - not us.
302317 return false ;
303318 }
304319
0 commit comments