Rizin
unix-like reverse engineering framework and cli tools
trap_arm.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2015 pancake <pancake@nopcode.org>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #if __arm || __arm64 || __arch64
5 
6 static int isThumb32(ut16 op) {
7  return (((op & 0xE000) == 0xE000) && (op & 0x1800));
8 }
9 
10 static bool ios_hwstep_enable64(RzDebug *dbg, bool enable) {
11  ARMDebugState64 ds;
12  thread_t th = getcurthread(dbg, NULL);
13 
14  mach_msg_type_number_t count = ARM_DEBUG_STATE64_COUNT;
15  if (thread_get_state(th, ARM_DEBUG_STATE64, (thread_state_t)&ds, &count)) {
16  perror("thread-get-state");
17  return false;
18  }
19  // The use of __arm64__ here is not ideal. If debugserver is running on
20  // an armv8 device, regardless of whether it was built for arch arm or
21  // arch arm64, it needs to use the MDSCR_EL1 SS bit to single
22  // instruction step.
23 
24  // MDSCR_EL1 single step bit at gpr.pc
25  if (enable) {
26  ds.mdscr_el1 |= 1LL;
27  } else {
28  ds.mdscr_el1 &= ~(1ULL);
29  }
30  if (thread_set_state(th, ARM_DEBUG_STATE64, (thread_state_t)&ds, count)) {
31  perror("thread-set-state");
32  }
33  return true;
34 }
35 
36 static bool ios_hwstep_enable32(RzDebug *dbg, bool enable) {
37  mach_msg_type_number_t count;
38  arm_unified_thread_state_t state = { { 0 } };
39  _STRUCT_ARM_DEBUG_STATE ds;
40  task_t task = 0;
41  thread_t th = getcurthread(dbg, &task);
42  int ret;
43 
44  count = ARM_DEBUG_STATE32_COUNT;
45  ret = thread_get_state(th, ARM_DEBUG_STATE32, (thread_state_t)&ds, &count);
46  if (ret != KERN_SUCCESS) {
47  perror("thread_get_state(debug)");
48  }
49 
50  count = ARM_UNIFIED_THREAD_STATE_COUNT;
51  ret = thread_get_state(th, ARM_UNIFIED_THREAD_STATE, (thread_state_t)&state, &count);
52  if (ret != KERN_SUCCESS) {
53  perror("thread_get_state(unified)");
54  }
55  // eprintf ("PC = 0x%08x\n", state.ts_32.__pc);
56  if (enable) {
57  int i;
58  RzIOBind *bio = &dbg->iob;
59  ut32 pc = state.ts_32.__pc;
60  ut32 cpsr = state.ts_32.__cpsr;
61  for (i = 0; i < 16; i++) {
62  ds.__bcr[i] = ds.__bvr[i] = 0;
63  }
64  i = 0;
65  ds.__bvr[i] = pc & (UT32_MAX >> 2) << 2;
66  ds.__bcr[i] = BCR_M_IMVA_MISMATCH | S_USER | BCR_ENABLE;
67  if (cpsr & 0x20) {
68  ut16 op;
69  if (pc & 2) {
70  ds.__bcr[i] |= BAS_IMVA_2_3;
71  } else {
72  ds.__bcr[i] |= BAS_IMVA_0_1;
73  }
74  /* check for thumb */
75  bio->read_at(bio->io, pc, (void *)&op, 2);
76  if (isThumb32(op)) {
77  eprintf("Thumb32 chain stepping not supported yet\n");
78  } else {
79  ds.__bcr[i] |= BAS_IMVA_ALL;
80  }
81  } else {
82  ds.__bcr[i] |= BAS_IMVA_ALL;
83  }
84  }
85  if (thread_set_state(th, ARM_DEBUG_STATE32, (thread_state_t)&ds, ARM_DEBUG_STATE32_COUNT)) {
86  perror("ios_hwstep_enable32");
87  return false;
88  }
89  return true;
90 }
91 
92 bool xnu_native_hwstep_enable(RzDebug *dbg, bool enable) {
93  if (dbg->bits == RZ_SYS_BITS_64 || dbg->bits == 64) {
94  return ios_hwstep_enable64(dbg, enable);
95  }
96  return ios_hwstep_enable32(dbg, enable);
97 }
98 #endif
ut8 op
Definition: 6502dis.c:13
lzma_index ** i
Definition: index.h:629
#define NULL
Definition: cris-opc.c:27
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void count
Definition: sflib.h:98
uint16_t ut16
uint32_t ut32
RzDebug * dbg
Definition: desil.c:30
#define eprintf(x, y...)
Definition: rlcc.c:7
@ RZ_SYS_BITS_64
Definition: rz_sys.h:21
#define UT32_MAX
Definition: rz_types_base.h:99
int bits
Definition: rz_debug.h:243
RzIOBind iob
Definition: rz_debug.h:293
RzIOReadAt read_at
Definition: rz_io.h:240
RzIO * io
Definition: rz_io.h:232
Definition: dis.h:43
Definition: dis.c:32