Rizin
unix-like reverse engineering framework and cli tools
xnu_debug.h
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2015 Álvaro Felipe Melchor <alvaro.felipe91@gmail.com>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 // code to support natively debugging mach binaries
5 /* _
6  _\‍)/_
7  / /
8  \ \
9  \_._/
10 */
11 #ifndef _XNU_DEBUG_H
12 #define _XNU_DEBUG_H
13 
14 #include <rz_util/rz_log.h>
15 #include <rz_debug.h>
16 
17 #define LOG_MACH_ERROR(name, rc) \
18  do { \
19  const char *str = mach_error_string(rc); \
20  RZ_LOG_ERROR("%s/%s: %s\n", __FUNCTION__, name, str ? str : "(unknown)"); \
21  } while (0)
22 
23 #if TARGET_OS_IPHONE
24 // no ptrace
25 #define PT_TRACE_ME 0 /* child declares it's being traced */
26 #define PT_READ_I 1 /* read word in child's I space */
27 #define PT_READ_D 2 /* read word in child's D space */
28 #define PT_READ_U 3 /* read word in child's user structure */
29 #define PT_WRITE_I 4 /* write word in child's I space */
30 #define PT_WRITE_D 5 /* write word in child's D space */
31 #define PT_WRITE_U 6 /* write word in child's user structure */
32 #define PT_CONTINUE 7 /* continue the child */
33 #define PT_KILL 8 /* kill the child process */
34 #define PT_STEP 9 /* single step the child */
35 #define PT_ATTACH 10 /* trace some running process */
36 #define PT_DETACH 11 /* stop tracing a process */
37 #define PT_SIGEXC 12 /* signals as exceptions for current_proc */
38 #define PT_THUPDATE 13 /* signal for thread# */
39 #define PT_ATTACHEXC 14 /* attach to running process with signal exception */
40 #define PT_FORCEQUOTA 30 /* Enforce quota for root */
41 #define PT_DENY_ATTACH 31
42 #define PT_FIRSTMACH 32 /* for machine-specific requests */
43 int ptrace(int _request, pid_t _pid, caddr_t _addr, int _data);
44 #else
45 #include <sys/ptrace.h>
46 #if !__POWERPC__
47 #include <sys/proc_info.h>
48 #include <libproc.h>
49 #define HAS_LIBPROC
50 #endif
51 #endif
52 #include <sys/types.h>
53 #include <sys/wait.h>
54 #include <mach/exception_types.h>
55 #include <mach/mach_init.h>
56 #include <mach/mach_port.h>
57 #include <mach/mach_interface.h>
58 #include <mach/mach_traps.h>
59 #include <mach/mach_types.h>
60 // no available for ios #include <mach/mach_vm.h>
61 #include <mach/mach_error.h>
62 #include <mach/task.h>
63 #include <mach/task_info.h>
64 #include <mach/thread_act.h>
65 #include <mach/thread_info.h>
66 #include <mach/vm_map.h>
67 #include <mach-o/loader.h>
68 #include <mach-o/nlist.h>
69 #include <errno.h>
70 #include <unistd.h>
71 #include <sys/sysctl.h>
72 #include <sys/fcntl.h>
73 #include <sys/proc.h>
74 
75 // G3
76 #if __POWERPC__
77 #include <sys/ptrace.h>
78 #include <sys/types.h>
79 #include <sys/wait.h>
80 #include <mach/ppc/_types.h>
81 #include <mach/ppc/thread_status.h>
82 // iPhone5
83 #elif __aarch64
84 #include <mach/aarch64/thread_status.h>
85 // iPhone
86 #elif __arm
87 #include <mach/arm/thread_status.h>
88 #elif __arm64
89 #include <mach/arm/thread_status.h>
90 #else
91 // iMac
92 /* x86 32/64 */
93 #include <mach/i386/thread_status.h>
94 #include <sys/ucontext.h>
95 #include <mach/i386/_structs.h>
96 
97 // APPLE
98 
99 /*
100 #if OLDIEDEF
101 #if __x86_64__
102 #define RZ_DEBUG_STATE_T x86_THREAD_STATE
103 #define RZ_DEBUG_REG_T _STRUCT_X86_THREAD_STATE64
104 #define RZ_DEBUG_STATE_SZ x86_THREAD_STATE_COUNT
105 #else
106 #define RZ_DEBUG_REG_T _STRUCT_X86_THREAD_STATE32
107 #define RZ_DEBUG_STATE_T i386_THREAD_STATE
108 #define RZ_DEBUG_STATE_SZ i386_THREAD_STATE_COUNT
109 #endif
110 #endif // OLDIEDEF
111 */
112 
113 #if __LP64__
114 #define ADDR "%16lx"
115 #define HEADER_SIZE 0x1000
116 #define IMAGE_OFFSET 0x2000
117 #define KERNEL_LOWER 0xffffff8000000000
118 #else
119 #define ADDR "%8x"
120 #define HEADER_SIZE 0x1000
121 #define IMAGE_OFFSET 0x201000
122 #define KERNEL_LOWER 0x80000000
123 #endif
124 //#define RZ_DEBUG_STATE_T XXX
125 //(dbg->bits==64)?x86_THREAD_STATE:_STRUCT_X86_THREAD_STATE32
126 //#define RZ_DEBUG_REG_T _STRUCT_X86_THREAD_STATE64
127 //#define RZ_DEBUG_STATE_SZ ((dbg->bits == RZ_SYS_BITS_64) ? 168 : 64)
128 #define REG_PC ((dbg->bits == RZ_SYS_BITS_64) ? 16 : 10)
129 #define REG_FL ((dbg->bits == RZ_SYS_BITS_64) ? 17 : 9)
130 #define REG_SP (7)
131 #endif
132 
133 #if TARGET_OS_IPHONE
134 
135 typedef struct {
136  ut64 bvr[16];
137  ut64 bcr[16];
138  ut64 wvr[16];
139  ut64 wcr[16];
140  ut64 mdscr_el1;
141 } ARMDebugState64;
142 
143 typedef struct {
144  ut32 bvr[16];
145  ut32 bcr[16];
146  ut32 wvr[16];
147  ut32 wcr[16];
148  ut64 mdscr_el1;
149 } ARMDebugState32;
150 
151 // BCR address match type
152 #define BCR_M_IMVA_MATCH ((uint32_t)(0u << 21))
153 #define BCR_M_CONTEXT_ID_MATCH ((uint32_t)(1u << 21))
154 #define BCR_M_IMVA_MISMATCH ((uint32_t)(2u << 21))
155 #define BCR_M_RESERVED ((uint32_t)(3u << 21))
156 
157 // Link a BVR/BCR or WVR/WCR pair to another
158 #define E_ENABLE_LINKING ((uint32_t)(1u << 20))
159 
160 // Byte Address Select
161 #define BAS_IMVA_PLUS_0 ((uint32_t)(1u << 5))
162 #define BAS_IMVA_PLUS_1 ((uint32_t)(1u << 6))
163 #define BAS_IMVA_PLUS_2 ((uint32_t)(1u << 7))
164 #define BAS_IMVA_PLUS_3 ((uint32_t)(1u << 8))
165 #define BAS_IMVA_0_1 ((uint32_t)(3u << 5))
166 #define BAS_IMVA_2_3 ((uint32_t)(3u << 7))
167 #define BAS_IMVA_ALL ((uint32_t)(0xfu << 5))
168 
169 // Break only in privileged or user mode
170 #define S_RSVD ((uint32_t)(0u << 1))
171 #define S_PRIV ((uint32_t)(1u << 1))
172 #define S_USER ((uint32_t)(2u << 1))
173 #define S_PRIV_USER ((S_PRIV) | (S_USER))
174 
175 #define BCR_ENABLE ((uint32_t)(1u))
176 #define WCR_ENABLE ((uint32_t)(1u))
177 
178 // Watchpoint load/store
179 #define WCR_LOAD ((uint32_t)(1u << 3))
180 #define WCR_STORE ((uint32_t)(1u << 4))
181 
182 #endif
183 
184 typedef struct {
185  int flavor;
186  mach_msg_type_number_t count;
188 
189 #if defined(__ppc__)
190 
192  thread_flavor_array[] = {
193  { PPC_THREAD_STATE, PPC_THREAD_STATE_COUNT },
194  { PPC_FLOAT_STATE, PPC_FLOAT_STATE_COUNT },
195  { PPC_EXCEPTION_STATE, PPC_EXCEPTION_STATE_COUNT },
196  { PPC_VECTOR_STATE, PPC_VECTOR_STATE_COUNT },
197  };
198 
199 static int coredump_nflavors = 4;
200 
201 #elif defined(__ppc64__)
202 
204  thread_flavor_array[] = {
205  { PPC_THREAD_STATE64, PPC_THREAD_STATE64_COUNT },
206  { PPC_FLOAT_STATE, PPC_FLOAT_STATE_COUNT },
207  { PPC_EXCEPTION_STATE64, PPC_EXCEPTION_STATE64_COUNT },
208  { PPC_VECTOR_STATE, PPC_VECTOR_STATE_COUNT },
209  };
210 
211 static int coredump_nflavors = 4;
212 
213 #elif defined(__i386__)
214 
216  thread_flavor_array[] = {
217  { x86_THREAD_STATE32, x86_THREAD_STATE32_COUNT },
218  { x86_FLOAT_STATE32, x86_FLOAT_STATE32_COUNT },
219  { x86_EXCEPTION_STATE32, x86_EXCEPTION_STATE32_COUNT },
220  };
221 
222 static int coredump_nflavors = 3;
223 
224 #elif defined(__x86_64__)
225 
227  thread_flavor_array[] = {
231  };
232 
233 static int coredump_nflavors = 3;
234 
235 #elif defined(__aarch64__) || defined(__arm64__)
236 
238  thread_flavor_array[] = {
239  { ARM_UNIFIED_THREAD_STATE, ARM_UNIFIED_THREAD_STATE_COUNT }
240  };
241 
242 static int coredump_nflavors = 1;
243 
244 #elif defined(__arm__)
245 
247  thread_flavor_array[] = {
248  { ARM_THREAD_STATE64, ARM_THREAD_STATE64_COUNT }
249  };
250 
251 static int coredump_nflavors = 1;
252 
253 #else
254 // XXX: Add __arm__ for iOS devices?
255 #warning Unsupported architecture
256 
257 #endif
258 
259 #define MAX_TSTATE_FLAVORS 10
260 #define DEFAULT_COREFILE_DEST "core.%u"
261 #define RZ_DEBUG_REASON_MACH_RCV_INTERRUPTED -2
262 
263 typedef struct {
264  vm_offset_t header;
265  int hoffset;
268 } tir_t;
269 
270 task_t pid_to_task(int pid);
274 int xnu_reg_read(RzDebug *dbg, int type, ut8 *buf, int size);
275 int xnu_reg_write(RzDebug *dgb, int type, const ut8 *buf, int size);
276 char *xnu_reg_profile(RzDebug *dbg);
277 int xnu_attach(RzDebug *dbg, int pid);
278 bool xnu_step(RzDebug *dbg);
279 int xnu_detach(RzDebug *dbg, int pid);
280 int xnu_stop(RzDebug *dbg, int pid);
281 int xnu_continue(RzDebug *dbg, int pid, int tid, int sig);
284 int xnu_map_protect(RzDebug *dbg, ut64 addr, int size, int perms);
285 int xnu_init(void);
286 int xnu_wait(RzDebug *dbg, int pid);
288 RzList *xnu_dbg_maps(RzDebug *dbg, int only_modules);
290 RzDebugInfo *xnu_info(RzDebug *dbg, const char *arg);
291 
292 #endif
uint32_t ut32
RzDebug * dbg
Definition: desil.c:30
voidpf void uLong size
Definition: ioapi.h:138
voidpf void * buf
Definition: ioapi.h:138
uint8_t ut8
Definition: lh5801.h:11
static void list(RzEgg *egg)
Definition: rz-gg.c:52
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc pid
Definition: sflib.h:64
static static fork const void static count static fd const char static mode const char static pathname const char static path const char static dev const char static group static getpid static getuid ptrace
Definition: sflib.h:57
char * dest
Definition: lz4.h:697
#define x86_EXCEPTION_STATE64_COUNT
#define x86_FLOAT_STATE64_COUNT
@ x86_EXCEPTION_STATE32
@ x86_THREAD_STATE64
@ x86_EXCEPTION_STATE64
@ x86_FLOAT_STATE64
@ x86_THREAD_STATE32
@ x86_FLOAT_STATE32
#define x86_THREAD_STATE64_COUNT
int type
Definition: mipsasm.c:17
int caddr_t
Definition: sftypes.h:62
int pid_t
Definition: sftypes.h:38
mach_msg_type_number_t count
Definition: xnu_debug.h:186
int hoffset
Definition: xnu_debug.h:265
coredump_thread_state_flavor_t * flavors
Definition: xnu_debug.h:267
int tstate_size
Definition: xnu_debug.h:266
vm_offset_t header
Definition: xnu_debug.h:264
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
char * xnu_reg_profile(RzDebug *dbg)
Definition: xnu_debug.c:252
bool xnu_step(RzDebug *dbg)
Definition: xnu_debug.c:112
int xnu_map_dealloc(RzDebug *dbg, ut64 addr, int size)
Definition: xnu_debug.c:368
int xnu_continue(RzDebug *dbg, int pid, int tid, int sig)
Definition: xnu_debug.c:227
RzDebugMap * xnu_map_alloc(RzDebug *dbg, ut64 addr, int size)
Definition: xnu_debug.c:346
int xnu_reg_write(RzDebug *dgb, int type, const ut8 *buf, int size)
Definition: xnu_debug.c:279
bool xnu_generate_corefile(RzDebug *dbg, RzBuffer *dest)
Definition: xnu_debug.c:827
int xnu_map_protect(RzDebug *dbg, ut64 addr, int size, int perms)
Definition: xnu_debug.c:486
RzList * xnu_dbg_maps(RzDebug *dbg, int only_modules)
Definition: xnu_debug.c:1225
RzDebugPid * xnu_get_pid(int pid)
Definition: xnu_debug.c:907
char * xnu_corefile_default_location(void)
int xnu_get_vmmap_entries_for_pid(pid_t pid)
Definition: xnu_debug.c:538
int xnu_init(void)
int xnu_detach(RzDebug *dbg, int pid)
Definition: xnu_debug.c:160
int xnu_stop(RzDebug *dbg, int pid)
Definition: xnu_debug.c:194
int xnu_reg_read(RzDebug *dbg, int type, ut8 *buf, int size)
Definition: xnu_debug.c:315
int xnu_wait(RzDebug *dbg, int pid)
Definition: xnu_debug.c:108
int xnu_attach(RzDebug *dbg, int pid)
Definition: xnu_debug.c:133
RzList * xnu_thread_list(RzDebug *dbg, int pid, RzList *list)
Definition: xnu_debug.c:453
task_t pid_to_task(int pid)
Definition: xnu_debug.c:498
RzDebugInfo * xnu_info(RzDebug *dbg, const char *arg)
Definition: xnu_debug.c:397
static int addr
Definition: z80asm.c:58