1 /* radare - LGPL - Copyright 2009-2016 - pancake, defragger, madprogrammer */
2 
3 #include <r_asm.h>
4 #include <r_debug.h>
5 #include <libqnxr.h>
6 
7 /* HACK_FOR_PLUGIN_LINKAGE */
__r_debug_pid_new(const char * path,int pid,char status,ut64 pc)8 R_API RDebugPid *__r_debug_pid_new(const char *path, int pid, char status, ut64 pc) {
9 	RDebugPid *p = R_NEW0 (RDebugPid);
10 	if (!p) {
11 		return NULL;
12 	}
13 	p->path = strdup (path);
14 	p->pid = pid;
15 	p->status = status;
16 	p->runnable = true;
17 	p->pc = pc;
18 	return p;
19 }
__r_debug_pid_free(RDebugPid * pid)20 R_API void *__r_debug_pid_free(RDebugPid *pid) {
21 	free (pid->path);
22 	free (pid);
23 	return NULL;
24 }
25 /* ------------------- */
26 
27 typedef struct {
28 	libqnxr_t desc;
29 } RIOQnx;
30 
31 static libqnxr_t *desc = NULL;
32 static ut8 *reg_buf = NULL;
33 static int buf_size = 0;
34 
pidlist_cb(void * ctx,pid_t pid,char * name)35 static void pidlist_cb (void *ctx, pid_t pid, char *name) {
36 	RList *list = ctx;
37 	r_list_append (list, __r_debug_pid_new (name, pid, 's', 0));
38 }
39 
r_debug_qnx_select(RDebug * dbg,int pid,int tid)40 static int r_debug_qnx_select (RDebug *dbg, int pid, int tid) {
41 	return qnxr_select (desc, pid, tid);
42 }
43 
r_debug_qnx_tids(RDebug * dbg,int pid)44 static RList *r_debug_qnx_tids (RDebug *dbg, int pid) {
45 	eprintf ("%s: TODO: Threads\n", __func__);
46 	return NULL;
47 }
48 
49 
r_debug_qnx_pids(RDebug * dbg,int pid)50 static RList *r_debug_qnx_pids (RDebug *dbg, int pid) {
51 	RList *list = r_list_new ();
52 	if (!list) {
53 		return NULL;
54 	}
55 	list->free = (RListFree)&__r_debug_pid_free;
56 
57 	/* TODO */
58 	if (pid) {
59 		r_list_append (list, __r_debug_pid_new ("(current)", pid, 's', 0));
60 	} else {
61 		qnxr_pidlist (desc, list, &pidlist_cb);
62 	}
63 
64 	return list;
65 }
66 
r_debug_qnx_reg_read(RDebug * dbg,int type,ut8 * buf,int size)67 static int r_debug_qnx_reg_read (RDebug *dbg, int type, ut8 *buf, int size) {
68 	int copy_size;
69 	int buflen = 0;
70 	if (!desc) {
71 		return -1;
72 	}
73 	int len = qnxr_read_registers (desc);
74 	if (len <= 0) {
75 		return -1;
76 	}
77 	// read the len of the current area
78 	free (r_reg_get_bytes (dbg->reg, type, &buflen));
79 	if (size < len) {
80 		eprintf ("r_debug_qnx_reg_read: small buffer %d vs %d\n",
81 			 (int)size, (int)len);
82 	}
83 	copy_size = R_MIN (len, size);
84 	buflen = R_MAX (len, buflen);
85 	if (reg_buf) {
86 		if (buf_size < copy_size) {
87 			ut8 *new_buf = realloc (reg_buf, copy_size);
88 			if (!new_buf) {
89 				return -1;
90 			}
91 			reg_buf = new_buf;
92 			buflen = copy_size;
93 			buf_size = len;
94 		}
95 	} else {
96 		reg_buf = calloc (buflen, 1);
97 		if (!reg_buf) {
98 			return -1;
99 		}
100 		buf_size = buflen;
101 	}
102 	memset ((void *)(volatile void *) buf, 0, size);
103 	memcpy ((void *)(volatile void *) buf, desc->recv.data, copy_size);
104 	memset ((void *)(volatile void *) reg_buf, 0, buflen);
105 	memcpy ((void *)(volatile void *) reg_buf, desc->recv.data, copy_size);
106 
107 	return len;
108 }
109 
r_debug_qnx_map_get(RDebug * dbg)110 static RList *r_debug_qnx_map_get (RDebug *dbg) {
111 	return NULL;
112 }
113 
r_debug_qnx_reg_write(RDebug * dbg,int type,const ut8 * buf,int size)114 static int r_debug_qnx_reg_write (RDebug *dbg, int type, const ut8 *buf, int size) {
115 	int buflen = 0;
116 	int bits = dbg->anal->bits;
117 	const char *pcname = r_reg_get_name (dbg->anal->reg, R_REG_NAME_PC);
118 	RRegItem *reg = r_reg_get (dbg->anal->reg, pcname, 0);
119 	if (!reg_buf) {
120 		// we cannot write registers before we once read them
121 		return -1;
122 	}
123 	if (reg) {
124 		if (dbg->anal->bits != reg->size) {
125 			bits = reg->size;
126 		}
127 	}
128 	free (r_reg_get_bytes (dbg->reg, type, &buflen));
129 	// some implementations of the gdb protocol are acting weird.
130 	// so winedbg is not able to write registers through the <G> packet
131 	// and also it does not return the whole gdb register profile after
132 	// calling <g>
133 	// so this workaround resizes the small register profile buffer
134 	// to the whole set and fills the rest with 0
135 	if (buf_size < buflen) {
136 		ut8 *new_buf = realloc (reg_buf, buflen * sizeof (ut8));
137 		if (!new_buf) {
138 			return -1;
139 		}
140 		reg_buf = new_buf;
141 		memset (new_buf + buf_size, 0, buflen - buf_size);
142 	}
143 
144 	RRegItem *current = NULL;
145 	for (;;) {
146 		current = r_reg_next_diff (dbg->reg, type, reg_buf, buflen, current, bits);
147 		if (!current) {
148 			break;
149 		}
150 		ut64 val = r_reg_get_value (dbg->reg, current);
151 		int bytes = bits / 8;
152 		qnxr_write_reg (desc, current->name, (char *)&val, bytes);
153 	}
154 	return true;
155 }
156 
r_debug_qnx_continue(RDebug * dbg,int pid,int tid,int sig)157 static int r_debug_qnx_continue (RDebug *dbg, int pid, int tid, int sig) {
158 	qnxr_continue (desc, -1);
159 	return true;
160 }
161 
r_debug_qnx_step(RDebug * dbg)162 static int r_debug_qnx_step (RDebug *dbg) {
163 	qnxr_step (desc, -1);
164 	return true;
165 }
166 
r_debug_qnx_wait(RDebug * dbg,int pid)167 static int r_debug_qnx_wait (RDebug *dbg, int pid) {
168 	ptid_t ptid = qnxr_wait (desc, pid);
169 	if (!ptid_equal (ptid, null_ptid)) {
170 		dbg->reason.signum = desc->signal;
171 		return desc->notify_type;
172 	}
173 	return 0;
174 }
175 
r_debug_qnx_stop(RDebug * dbg)176 static int r_debug_qnx_stop (RDebug *dbg) {
177 	qnxr_stop (desc);
178 	return true;
179 }
180 
r_debug_qnx_attach(RDebug * dbg,int pid)181 static int r_debug_qnx_attach (RDebug *dbg, int pid) {
182 	RIODesc *d = dbg->iob.io->desc;
183 	dbg->swstep = false;
184 
185 	if (d && d->plugin && d->plugin->name && d->data) {
186 		if (!strcmp ("qnx", d->plugin->name)) {
187 			RIOQnx *g = d->data;
188 			int arch = r_sys_arch_id (dbg->arch);
189 			int bits = dbg->anal->bits;
190 			if ((desc = &g->desc)) {
191 				switch (arch) {
192 				case R_SYS_ARCH_X86:
193 					if (bits == 16 || bits == 32) {
194 						qnxr_set_architecture (&g->desc, X86_32);
195 					} else {
196 						eprintf ("Not supported register %s %d profile\n", dbg->arch, bits);
197 						return false;
198 					}
199 					break;
200 				case R_SYS_ARCH_ARM:
201 					if (bits == 16 || bits == 32) {
202 						qnxr_set_architecture (&g->desc, ARM_32);
203 					} else {
204 						eprintf ("Not supported register %s %d profile\n", dbg->arch, bits);
205 						return false;
206 					}
207 					break;
208 				}
209 			}
210 			if (pid) {
211 				qnxr_attach (desc, pid);
212 			}
213 		} else {
214 			eprintf ("%s: error: underlying IO descriptor isn't a QNX one\n", __func__);
215 			return false;
216 		}
217 	}
218 
219 	dbg->pid = 0;
220 	return true;
221 }
222 
r_debug_qnx_detach(RDebug * dbg,int pid)223 static int r_debug_qnx_detach (RDebug *dbg, int pid) {
224 	qnxr_disconnect (desc);
225 	free (reg_buf);
226 	return true;
227 }
228 
r_debug_qnx_reg_profile(RDebug * dbg)229 static const char *r_debug_qnx_reg_profile (RDebug *dbg) {
230 	int arch = r_sys_arch_id (dbg->arch);
231 	int bits = dbg->anal->bits;
232 	switch (arch) {
233 	case R_SYS_ARCH_X86:
234 		return strdup (
235 			"=PC	eip\n"
236 			"=SP	esp\n"
237 			"=BP	ebp\n"
238 			"=A0	eax\n"
239 			"=A1	ebx\n"
240 			"=A2	ecx\n"
241 			"=A3	edi\n"
242 			"gpr	eax	.32	0	0\n"
243 			"gpr	ecx	.32	4	0\n"
244 			"gpr	edx	.32	8	0\n"
245 			"gpr	ebx	.32	12	0\n"
246 			"gpr	esp	.32	16	0\n"
247 			"gpr	ebp	.32	20	0\n"
248 			"gpr	esi	.32	24	0\n"
249 			"gpr	edi	.32	28	0\n"
250 			"gpr	eip	.32	32	0\n"
251 			"gpr	eflags	.32	36	0\n"
252 			"seg	cs	.32	40	0\n"
253 			"seg	ss	.32	44	0\n"
254 #if 0
255 			"seg	ds	.32	48	0\n"
256 			"seg	es	.32	52	0\n"
257 			"seg	fs	.32	56	0\n"
258 			"seg	gs	.32	60	0\n"
259 #endif
260 			);
261 	case R_SYS_ARCH_ARM:
262 		if (bits == 32) {
263 			return strdup (
264 				"=PC	r15\n"
265 				"=SP	r14\n" // XXX
266 				"=A0	r0\n"
267 				"=A1	r1\n"
268 				"=A2	r2\n"
269 				"=A3	r3\n"
270 				"gpr	r0	.32	0	0\n"
271 				"gpr	r1	.32	4	0\n"
272 				"gpr	r2	.32	8	0\n"
273 				"gpr	r3	.32	12	0\n"
274 				"gpr	r4	.32	16	0\n"
275 				"gpr	r5	.32	20	0\n"
276 				"gpr	r6	.32	24	0\n"
277 				"gpr	r7	.32	28	0\n"
278 				"gpr	r8	.32	32	0\n"
279 				"gpr	r9	.32	36	0\n"
280 				"gpr	r10	.32	40	0\n"
281 				"gpr	r11	.32	44	0\n"
282 				"gpr	r12	.32	48	0\n"
283 				"gpr	sp	.32	52	0\n" // r13
284 				"gpr	lr	.32	56	0\n" // r14
285 				"gpr	pc	.32	60	0\n" // r15
286 				"gpr	r13	.32	52	0\n"
287 				"gpr	r14	.32	56	0\n"
288 				"gpr	r15	.32	60	0\n"
289 				"gpr	cpsr	.96	64	0\n"
290 				"mmx	d0	.64	68	0\n" // neon
291 				"mmx	d1	.64	76	0\n" // neon
292 				"mmx	d2	.64	84	0\n" // neon
293 				"mmx	d3	.64	92	0\n" // neon
294 				"mmx	d4	.64	100	0\n" // neon
295 				"mmx	d5	.64	108	0\n" // neon
296 				"mmx	d6	.64	116	0\n" // neon
297 				"mmx	d7	.64	124	0\n" // neon
298 				"mmx	d8	.64	132	0\n" // neon
299 				"mmx	d9	.64	140	0\n" // neon
300 				"mmx	d10	.64	148	0\n" // neon
301 				"mmx	d11	.64	156	0\n" // neon
302 				"mmx	d12	.64	164	0\n" // neon
303 				"mmx	d13	.64	172	0\n" // neon
304 				"mmx	d14	.64	180	0\n" // neon
305 				"mmx	d15	.64	188	0\n" // neon
306 				"mmx	d16	.64	196	0\n" // neon
307 				"mmx	d17	.64	204	0\n" // neon
308 				"mmx	d18	.64	212	0\n" // neon
309 				"mmx	d19	.64	220	0\n" // neon
310 				"mmx	d20	.64	228	0\n" // neon
311 				"mmx	d21	.64	236	0\n" // neon
312 				"mmx	d22	.64	244	0\n" // neon
313 				"mmx	d23	.64	252	0\n" // neon
314 				"mmx	d24	.64	260	0\n" // neon
315 				"mmx	d25	.64	268	0\n" // neon
316 				"mmx	d26	.64	276	0\n" // neon
317 				"mmx	d27	.64	284	0\n" // neon
318 				"mmx	d28	.64	292	0\n" // neon
319 				"mmx	d29	.64	300	0\n" // neon
320 				"mmx	d30	.64	308	0\n" // neon
321 				"mmx	d31	.64	316	0\n" // neon
322 				"mmx	fpscr	.32	324	0\n" // neon
323 			);
324 		}
325 	}
326 	return NULL;
327 }
328 
r_debug_qnx_breakpoint(RBreakpoint * bp,RBreakpointItem * b,bool set)329 static int r_debug_qnx_breakpoint (RBreakpoint *bp, RBreakpointItem *b, bool set) {
330 	if (!b) {
331 		return false;
332 	}
333 	int ret = set
334 		? b->hw
335 			? qnxr_set_hwbp (desc, b->addr, "")
336 			: qnxr_set_bp (desc, b->addr, "")
337 		: b->hw
338 			? qnxr_remove_hwbp (desc, b->addr)
339 			: qnxr_remove_bp (desc, b->addr);
340 	return !ret;
341 }
342 
343 RDebugPlugin r_debug_plugin_qnx = {
344 	.name = "qnx",
345 	.license = "LGPL3",
346 	.arch = "x86,arm",
347 	.bits = R_SYS_BITS_32,
348 	.step = r_debug_qnx_step,
349 	.cont = r_debug_qnx_continue,
350 	.attach = &r_debug_qnx_attach,
351 	.detach = &r_debug_qnx_detach,
352 	.pids = &r_debug_qnx_pids,
353 	.tids = &r_debug_qnx_tids,
354 	.select = &r_debug_qnx_select,
355 	.stop = &r_debug_qnx_stop,
356 	.canstep = 1,
357 	.wait = &r_debug_qnx_wait,
358 	.map_get = r_debug_qnx_map_get,
359 	.breakpoint = r_debug_qnx_breakpoint,
360 	.reg_read = &r_debug_qnx_reg_read,
361 	.reg_write = &r_debug_qnx_reg_write,
362 	.reg_profile = (void *)r_debug_qnx_reg_profile,
363 };
364 
365 #ifndef R2_PLUGIN_INCORE
366 R_API RLibStruct radare_plugin = {
367 	.type = R_LIB_TYPE_DBG,
368 	.data = &r_debug_plugin_qnx,
369 	.version = R2_VERSION};
370 #endif
371