1 /* libqnxr - GPL - Copyright 2016 - defragger, madprogrammer, FSF Inc */
2 
3 #include <errno.h>
4 #include <r_debug.h>
5 #include "libqnxr.h"
6 #include "core.h"
7 #include "signal.h"
8 #include "sigutil.h"
9 #include "packet.h"
10 
11 #define MAX_TRAN_TRIES 3
12 #define HOST_QNX_PROTOVER_MAJOR 0
13 #define HOST_QNX_PROTOVER_MINOR 3
14 
15 ptid_t null_ptid = {0, 0};
16 
17 void nto_send_init (libqnxr_t *g, ut32 cmd, ut32 subcmd, ut32 chan);
18 
19 ptid_t nto_parse_notify (libqnxr_t *g);
20 int nto_send_env (libqnxr_t *g, const char *env);
21 int nto_send_arg (libqnxr_t *g, const char *arg);
22 int nto_send (libqnxr_t *g, ut32 len, int report_errors);
23 
24 static registers_t x86_32[] = {
25 	{"eax", 0, 4},
26 	{"ecx", 4, 4},
27 	{"edx", 8, 4},
28 	{"ebx", 12, 4},
29 	{"esp", 16, 4},
30 	{"ebp", 20, 4},
31 	{"esi", 24, 4},
32 	{"edi", 28, 4},
33 	{"eip", 32, 4},
34 	{"eflags", 36, 4},
35 	{"cs", 40, 4},
36 	{"ss", 44, 4},
37 #if 0
38 	{"ds",	48,	4},
39 	{"es",	52,	4},
40 	{"fs",	56,	4},
41 	{"gs",	60,	4},
42 	{"st0",	64,	10},
43 	{"st1",	74,	10},
44 	{"st2",	84,	10},
45 	{"st3",	94,	10},
46 	{"st4",	104,	10},
47 	{"st5",	114,	10},
48 	{"st6",	124,	10},
49 	{"st7",	134,	10},
50 	{"fctrl",	144,	4},
51 	{"fstat",	148,	4},
52 	{"ftag",	152,	4},
53 	{"fiseg",	156,	4},
54 	{"fioff",	160,	4},
55 	{"foseg",	164,	4},
56 	{"fooff",	168,	4},
57 	{"fop",	172,	4},
58 	{"xmm0",	176,	16},
59 	{"xmm1",	192,	16},
60 	{"xmm2",	208,	16},
61 	{"xmm3",	224,	16},
62 	{"xmm4",	240,	16},
63 	{"xmm5",	256,	16},
64 	{"xmm6",	272,	16},
65 	{"xmm7",	288,	16},
66 	{"mxcsr",	304,	4},
67 #endif
68 	{"", 0, 0}};
69 
70 static registers_t arm32[] = {
71 	{"r0", 0, 4},
72 	{"r1", 4, 4},
73 	{"r2", 8, 4},
74 	{"r3", 12, 4},
75 	{"r4", 16, 4},
76 	{"r5", 20, 4},
77 	{"r6", 24, 4},
78 	{"r7", 28, 4},
79 	{"r8", 32, 4},
80 	{"r9", 36, 4},
81 	{"r10", 40, 4},
82 	{"r11", 44, 4},
83 	{"r12", 48, 4},
84 	{"sp", 52, 4},
85 	{"lr", 56, 4},
86 	{"pc", 60, 4},
87 	{"f0", 64, 12},
88 	{"f1", 76, 12},
89 	{"f2", 88, 12},
90 	{"f3", 100, 12},
91 	{"f4", 112, 12},
92 	{"f5", 124, 12},
93 	{"f6", 136, 12},
94 	{"f7", 148, 12},
95 	{"fps", 160, 12},
96 	{"cpsr", 172, 4},
97 	{"", 0, 0}};
98 
qnxr_init(libqnxr_t * g)99 int qnxr_init (libqnxr_t *g) {
100 	if (!g) return -1;
101 	memset (g, 0, sizeof (libqnxr_t));
102 	g->send_len = 0;
103 	g->send_buff = (char *)calloc (DS_DATA_MAX_SIZE * 2, 1);
104 	if (!g->send_buff)
105 		return -1;
106 	g->read_buff = (char *)calloc (DS_DATA_MAX_SIZE * 2, 1);
107 	if (!g->read_buff) {
108 		R_FREE (g->send_buff);
109 		return -1;
110 	}
111 	g->registers = x86_32;
112 	return 0;
113 }
114 
qnxr_set_architecture(libqnxr_t * g,ut8 architecture)115 int qnxr_set_architecture (libqnxr_t *g, ut8 architecture) {
116 	if (!g) return -1;
117 	g->architecture = architecture;
118 	switch (architecture) {
119 	case ARCH_X86_32:
120 		g->registers = x86_32;
121 		break;
122 	case ARCH_ARM_32:
123 		g->registers = arm32;
124 		break;
125 	default:
126 		eprintf ("Error unknown architecture set\n");
127 	}
128 	return 0;
129 }
130 
qnxr_cleanup(libqnxr_t * g)131 int qnxr_cleanup (libqnxr_t *g) {
132 	if (!g) return -1;
133 	free (g->send_buff);
134 	g->send_len = 0;
135 	free (g->read_buff);
136 	return 0;
137 }
138 
qnxr_connect(libqnxr_t * g,const char * host,int port)139 int qnxr_connect (libqnxr_t *g, const char *host, int port) {
140 	char tmp[255];
141 	int ret;
142 	if (!g || !host || g->connected) return -1;
143 
144 	g->data_len = 0;
145 	g->read_len = 0;
146 	g->read_ptr = 0;
147 	g->sock = r_socket_new (0);
148 	g->connected = 0;
149 	g->mid = 0;
150 
151 
152 	memmove (g->host, host, strlen (host) + 1);
153 	g->port = port;
154 
155 	ret = snprintf (tmp, sizeof (tmp) - 1, "%d", port);
156 	if (!ret) return -1;
157 	ret = r_socket_connect_tcp (g->sock, host, tmp, 200);
158 	if (!ret) return -1;
159 	g->connected = 1;
160 
161 	qnxr_send_ch_reset (g);
162 	nto_send_init (g, DStMsg_connect, 0, SET_CHANNEL_DEBUG);
163 	g->tran.pkt.connect.major = HOST_QNX_PROTOVER_MAJOR;
164 	g->tran.pkt.connect.minor = HOST_QNX_PROTOVER_MINOR;
165 	nto_send (g, sizeof (g->tran.pkt.connect), 0);
166 
167 	if (g->recv.pkt.hdr.cmd == DSrMsg_err) {
168 		eprintf ("%s: connection failed: %lld\n", __func__,
169 			 EXTRACT_SIGNED_INTEGER (&g->recv.pkt.err.err, 4));
170 		return -1;
171 	}
172 
173 	/* Try to query pdebug for their version of the protocol */
174 	nto_send_init (g, DStMsg_protover, 0, SET_CHANNEL_DEBUG);
175 	g->tran.pkt.protover.major = HOST_QNX_PROTOVER_MAJOR;
176 	g->tran.pkt.protover.minor = HOST_QNX_PROTOVER_MINOR;
177 	nto_send (g, sizeof (g->tran.pkt.protover), 0);
178 
179 	if ((g->recv.pkt.hdr.cmd == DSrMsg_err) && (EXTRACT_SIGNED_INTEGER (&g->recv.pkt.err.err, 4) == EINVAL)) {
180 		g->target_proto_major = 0;
181 		g->target_proto_minor = 0;
182 	} else if (g->recv.pkt.hdr.cmd == DSrMsg_okstatus) {
183 		g->target_proto_major = EXTRACT_SIGNED_INTEGER (&g->recv.pkt.okstatus.status, 4);
184 		g->target_proto_minor = EXTRACT_SIGNED_INTEGER (&g->recv.pkt.okstatus.status, 4);
185 		g->target_proto_major = (g->target_proto_major >> 8) & DSMSG_PROTOVER_MAJOR;
186 		g->target_proto_minor = g->target_proto_minor & DSMSG_PROTOVER_MINOR;
187 	} else {
188 		eprintf ("Connection failed (Protocol Version Query): %lld\n",
189 			 EXTRACT_SIGNED_INTEGER (&g->recv.pkt.err.err, 4));
190 		return -1;
191 	}
192 
193 	return 0;
194 }
195 
qnxr_disconnect(libqnxr_t * g)196 int qnxr_disconnect (libqnxr_t *g) {
197 	if (!g) return -1;
198 
199 	if (g->connected) {
200 		nto_send_init (g, DStMsg_disconnect, 0, SET_CHANNEL_DEBUG);
201 		nto_send (g, sizeof (g->tran.pkt.disconnect), 0);
202 		g->connected = 0;
203 		g->inferior_ptid = null_ptid;
204 
205 		if (!r_socket_close (g->sock))
206 			return -1;
207 	}
208 
209 	return 0;
210 }
211 
qnxr_attach(libqnxr_t * g,pid_t pid)212 ptid_t qnxr_attach (libqnxr_t *g, pid_t pid) {
213 
214 	if (g->inferior_ptid.pid != pid) {
215 		qnxr_disconnect (g);
216 		r_sys_sleep (1);
217 		qnxr_connect (g, g->host, g->port);
218 	}
219 
220 	nto_send_init (g, DStMsg_attach, 0, SET_CHANNEL_DEBUG);
221 	g->tran.pkt.attach.pid = pid;
222 	g->tran.pkt.attach.pid = EXTRACT_SIGNED_INTEGER (&g->tran.pkt.attach.pid, 4);
223 
224 	nto_send (g, sizeof (g->tran.pkt.attach), 0);
225 	if (g->recv.pkt.hdr.cmd != DSrMsg_okdata) {
226 		eprintf ("%s: failed to attach to %d\n", __func__, pid);
227 		return null_ptid;
228 	}
229 
230 	g->inferior_ptid = ptid_build (
231 		EXTRACT_SIGNED_INTEGER (&g->recv.pkt.notify.pid, 4),
232 		EXTRACT_SIGNED_INTEGER (&g->recv.pkt.notify.tid, 4));
233 
234 	return g->inferior_ptid;
235 }
236 
qnxr_run(libqnxr_t * g,const char * file,char ** args,char ** env)237 ptid_t qnxr_run (libqnxr_t *g, const char *file, char **args, char **env) {
238 	ut32 argc = 0;
239 	ut32 envc = 0;
240 
241 	char **argv, *p;
242 	int errors = 0;
243 
244 	if (!g) return null_ptid;
245 
246 	nto_send_init (g, DStMsg_env, DSMSG_ENV_CLEARENV, SET_CHANNEL_DEBUG);
247 	nto_send (g, sizeof (DStMsg_env_t), 1);
248 
249 	for (envc = 0; *env; env++, envc++)
250 		errors += !nto_send_env (g, *env);
251 
252 	if (errors) {
253 		eprintf ("%s: error(s) occurred while sending environment\n", __func__);
254 	}
255 
256 	nto_send_init (g, DStMsg_env, DSMSG_ENV_CLEARARGV, SET_CHANNEL_DEBUG);
257 	nto_send (g, sizeof (DStMsg_env_t), 1);
258 
259 	if (file != NULL) {
260 		errors = !nto_send_arg (g, file);
261 		if (!errors)
262 			errors = !nto_send_arg (g, file);
263 
264 		if (errors) {
265 			eprintf ("%s: failed to send executable file name\n", __func__);
266 			return null_ptid;
267 		}
268 
269 		errors = 0;
270 		for (argv = args; *argv && **argv; argv++, argc++)
271 			errors |= !nto_send_arg (g, *argv);
272 
273 		if (errors) {
274 			eprintf ("%s: error(s) occurred while sending args\n", __func__);
275 		}
276 	}
277 
278 	if (errors) {
279 		return null_ptid;
280 	}
281 
282 	nto_send_init (g, DStMsg_load, DSMSG_LOAD_DEBUG, SET_CHANNEL_DEBUG);
283 	p = g->tran.pkt.load.cmdline;
284 
285 	g->tran.pkt.load.envc = 0;
286 	g->tran.pkt.load.argc = 0;
287 
288 	if (file) {
289 		strncpy (p, file, sizeof (g->tran.pkt.load.cmdline) - 8);
290 		p += strlen (p);
291 	}
292 	*p++ = '\0';
293 
294 	*p++ = '\0'; // stdin
295 	*p++ = '\0'; // stdout
296 	*p++ = '\0'; // stderr
297 
298 	nto_send (g, offsetof (DStMsg_load_t, cmdline) + p - g->tran.pkt.load.cmdline + 1, 1);
299 
300 	if (g->recv.pkt.hdr.cmd == DSrMsg_okdata) {
301 		ptid_t ptid = nto_parse_notify (g);
302 		eprintf ("%s: inferior pid: %d\n", __func__, ptid.pid);
303 		g->inferior_ptid = ptid;
304 
305 		return ptid;
306 	}
307 
308 	return null_ptid;
309 }
310 
qnxr_read_registers(libqnxr_t * g)311 int qnxr_read_registers (libqnxr_t *g) {
312 	int i = 0;
313 	int len, rlen, regset;
314 	int n = 0;
315 	ut32 off;
316 	char buf[DS_DATA_MAX_SIZE];
317 
318 	if (!g) return -1;
319 
320 	while (g->registers[i].size > 0) {
321 		regset = i386nto_regset_id (i);
322 		len = i386nto_register_area (i, regset, &off);
323 		if (len < 1) {
324 			eprintf ("%s: unknown register %d\n", __func__, i);
325 			len = g->registers[i].size;
326 		}
327 		nto_send_init (g, DStMsg_regrd, regset, SET_CHANNEL_DEBUG);
328 		g->tran.pkt.regrd.offset = EXTRACT_SIGNED_INTEGER (&off, 2);
329 		g->tran.pkt.regrd.size = EXTRACT_SIGNED_INTEGER (&len, 2);
330 		rlen = nto_send (g, sizeof (g->tran.pkt.regrd), 1);
331 
332 		if (rlen > 0) {
333 			if (g->recv.pkt.hdr.cmd == DSrMsg_okdata) {
334 				memcpy (buf + g->registers[i].offset,
335 					g->recv.pkt.okdata.data, len);
336 				n += len;
337 			} else {
338 				memset (buf + g->registers[i].offset,
339 					0, len);
340 			}
341 		} else {
342 			eprintf ("%s: couldn't read register %d\n", __func__, i);
343 			return -1;
344 		}
345 		i++;
346 	}
347 
348 	memcpy (g->recv.data, buf, n);
349 	return n;
350 }
351 
qnxr_read_memory(libqnxr_t * g,ut64 address,ut8 * data,ut64 len)352 int qnxr_read_memory (libqnxr_t *g, ut64 address, ut8 *data, ut64 len) {
353 	int rcv_len, tot_len, ask_len;
354 	ut64 addr;
355 
356 	if (!g || !data) return -1;
357 
358 	tot_len = rcv_len = ask_len = 0;
359 
360 	do {
361 		nto_send_init (g, DStMsg_memrd, 0, SET_CHANNEL_DEBUG);
362 		addr = address + tot_len;
363 		g->tran.pkt.memrd.addr = EXTRACT_UNSIGNED_INTEGER (&addr, 8);
364 		ask_len = ((len - tot_len) > DS_DATA_MAX_SIZE) ?
365 				  DS_DATA_MAX_SIZE :
366 				  (len - tot_len);
367 
368 		g->tran.pkt.memrd.size = EXTRACT_SIGNED_INTEGER (&ask_len, 2);
369 		rcv_len = nto_send (g, sizeof (g->tran.pkt.memrd), 0) -
370 			  sizeof (g->recv.pkt.hdr);
371 		if (rcv_len <= 0) break;
372 		if (g->recv.pkt.hdr.cmd == DSrMsg_okdata) {
373 			memcpy (data + tot_len, g->recv.pkt.okdata.data, rcv_len);
374 			tot_len += rcv_len;
375 		} else
376 			break;
377 	} while (tot_len != len);
378 
379 	return tot_len;
380 }
381 
qnxr_write_memory(libqnxr_t * g,ut64 address,const ut8 * data,ut64 len)382 int qnxr_write_memory (libqnxr_t *g, ut64 address, const ut8 *data, ut64 len) {
383 	ut64 addr;
384 
385 	if (!g || !data) return -1;
386 
387 	nto_send_init (g, DStMsg_memwr, 0, SET_CHANNEL_DEBUG);
388 	addr = address;
389 	g->tran.pkt.memwr.addr = EXTRACT_UNSIGNED_INTEGER (&addr, 8);
390 	memcpy (g->tran.pkt.memwr.data, data, len);
391 	nto_send (g, offsetof (DStMsg_memwr_t, data) + len, 0);
392 
393 	switch (g->recv.pkt.hdr.cmd) {
394 	case DSrMsg_ok:
395 		return len;
396 	case DSrMsg_okstatus:
397 		return EXTRACT_SIGNED_INTEGER (&g->recv.pkt.okstatus.status, 4);
398 	}
399 
400 	return 0;
401 }
402 
qnxr_pidlist(libqnxr_t * g,void * ctx,pidlist_cb_t * cb)403 void qnxr_pidlist (libqnxr_t *g, void *ctx, pidlist_cb_t *cb) {
404 	struct dspidlist *pidlist = (void *)g->recv.pkt.okdata.data;
405 	pid_t pid, start_tid;
406 	char subcmd;
407 
408 	if (!g) return;
409 
410 	start_tid = 1;
411 	pid = 1;
412 	subcmd = DSMSG_PIDLIST_BEGIN;
413 
414 	while (1) {
415 		nto_send_init (g, DStMsg_pidlist, subcmd, SET_CHANNEL_DEBUG);
416 		g->tran.pkt.pidlist.pid = EXTRACT_SIGNED_INTEGER (&pid, 4);
417 		g->tran.pkt.pidlist.tid = EXTRACT_SIGNED_INTEGER (&start_tid, 4);
418 		nto_send (g, sizeof (g->tran.pkt.pidlist), 0);
419 
420 		if (g->recv.pkt.hdr.cmd == DSrMsg_err || g->recv.pkt.hdr.cmd != DSrMsg_okdata)
421 			return;
422 
423 		pid = EXTRACT_SIGNED_INTEGER (&pidlist->pid, 4);
424 		if (cb != NULL)
425 			cb (ctx, pid, pidlist->name);
426 		subcmd = DSMSG_PIDLIST_NEXT;
427 	}
428 }
429 
qnxr_select(libqnxr_t * g,pid_t pid,int tid)430 int qnxr_select (libqnxr_t *g, pid_t pid, int tid) {
431 	if (!g) return 0;
432 
433 	/* TODO */
434 	tid = 1;
435 
436 	nto_send_init (g, DStMsg_select, DSMSG_SELECT_SET, SET_CHANNEL_DEBUG);
437 	g->tran.pkt.select.pid = pid;
438 	g->tran.pkt.select.pid = EXTRACT_SIGNED_INTEGER (&g->tran.pkt.select.pid, 4);
439 	g->tran.pkt.select.tid = EXTRACT_SIGNED_INTEGER (&tid, 4);
440 	nto_send (g, sizeof (g->tran.pkt.select), 1);
441 
442 	if (g->recv.pkt.hdr.cmd == DSrMsg_err) {
443 		eprintf ("%s: failed to select %d\n", __func__, pid);
444 		return 0;
445 	}
446 
447 	return 1;
448 }
449 
qnxr_step(libqnxr_t * g,int thread_id)450 int qnxr_step (libqnxr_t *g, int thread_id) {
451 	return qnxr_send_vcont (g, 1, thread_id);
452 }
453 
qnxr_continue(libqnxr_t * g,int thread_id)454 int qnxr_continue (libqnxr_t *g, int thread_id) {
455 	return qnxr_send_vcont (g, 0, thread_id);
456 }
457 
qnxr_write_register(libqnxr_t * g,int index,char * value,int len)458 int qnxr_write_register (libqnxr_t *g, int index, char *value, int len) {
459 	int tdep_len, regset;
460 	ut32 off;
461 
462 	if (!g) return -1;
463 
464 	regset = i386nto_regset_id (index);
465 	tdep_len = i386nto_register_area (index, regset, &off);
466 	if (len < 0 || tdep_len != len) {
467 		eprintf ("%s: invalid length\n", __func__);
468 		return -1;
469 	}
470 
471 	nto_send_init (g, DStMsg_regwr, regset, SET_CHANNEL_DEBUG);
472 	g->tran.pkt.regwr.offset = EXTRACT_SIGNED_INTEGER (&off, 2);
473 	memcpy (g->tran.pkt.regwr.data, value, len);
474 	nto_send (g, offsetof (DStMsg_regwr_t, data) + len, 1);
475 
476 	return 0;
477 }
478 
qnxr_write_reg(libqnxr_t * g,const char * name,char * value,int len)479 int qnxr_write_reg (libqnxr_t *g, const char *name, char *value, int len) {
480 	int i = 0;
481 
482 	if (!g) return -1;
483 
484 	while (g->registers[i].size > 0) {
485 		if (!strcmp (g->registers[i].name, name)) {
486 			break;
487 		}
488 		i++;
489 	}
490 	if (g->registers[i].size == 0) {
491 		eprintf ("Error registername <%s> not found in profile\n", name);
492 		return -1;
493 	}
494 	qnxr_write_register (g, i, value, len);
495 
496 	return 0;
497 }
498 
qnxr_send_vcont(libqnxr_t * g,int step,int thread_id)499 int qnxr_send_vcont (libqnxr_t *g, int step, int thread_id) {
500 	if (!g) return -1;
501 
502 	nto_send_init (g, DStMsg_run, step ? DSMSG_RUN_COUNT : DSMSG_RUN,
503 		       SET_CHANNEL_DEBUG);
504 	g->tran.pkt.run.step.count = 1;
505 	nto_send (g, sizeof (g->tran.pkt.run), 1);
506 	return 0;
507 }
508 
qnxr_stop(libqnxr_t * g)509 int qnxr_stop (libqnxr_t *g) {
510 	if (!g) return 0;
511 
512 	eprintf ("%s: waiting for stop\n", __func__);
513 	g->waiting_for_stop = 1;
514 	nto_send_init (g, DStMsg_stop, DSMSG_STOP_PIDS, SET_CHANNEL_DEBUG);
515 
516 	g->send_len = sizeof (g->tran.pkt.stop);
517 	qnxr_send_packet (g);
518 
519 	return 1;
520 }
521 
qnxr_wait(libqnxr_t * g,pid_t pid)522 ptid_t qnxr_wait (libqnxr_t *g, pid_t pid) {
523 	if (!g || pid < 0) {
524 		return null_ptid;
525 	}
526 	ptid_t returned_ptid = g->inferior_ptid;
527 	if (g->inferior_ptid.pid != pid) {
528 		return null_ptid;
529 	}
530 	if (g->recv.pkt.hdr.cmd != DShMsg_notify) {
531 		int rlen;
532 		char waiting_for_notify = 1;
533 
534 		eprintf ("%s: waiting for inferior\n", __func__);
535 
536 		while (1) {
537 			rlen = qnxr_read_packet (g);
538 			if (rlen == -1) {
539 				if (g->waiting_for_stop) {
540 					eprintf ("%s: read eror while waiting for stop\n",
541 						 __func__);
542 					continue;
543 				} else {
544 					eprintf ("%s: read packet error or NAK\n", __func__);
545 					return null_ptid;
546 				}
547 			}
548 			if (g->channelrd == SET_CHANNEL_TEXT) {
549 				// TODO nto_incoming_text
550 			} else {
551 				g->recv.pkt.hdr.cmd &= ~DSHDR_MSG_BIG_ENDIAN;
552 				if (g->waiting_for_stop && g->recv.pkt.hdr.cmd == DSrMsg_ok) {
553 					g->waiting_for_stop = 0;
554 					eprintf ("%s: got stop response\n", __func__);
555 					if (!waiting_for_notify)
556 						break;
557 				} else if (g->recv.pkt.hdr.cmd == DShMsg_notify) {
558 					// acknowledge the notify
559 					g->tran.pkt.hdr.cmd = DSrMsg_ok;
560 					g->tran.pkt.hdr.channel = SET_CHANNEL_DEBUG;
561 					g->tran.pkt.hdr.mid = g->recv.pkt.hdr.mid;
562 					qnxr_send_ch_debug (g);
563 
564 					g->send_len = sizeof (g->tran.pkt.ok);
565 					qnxr_send_packet (g);
566 
567 					returned_ptid = nto_parse_notify (g);
568 					break;
569 				}
570 			}
571 		}
572 	}
573 
574 	/* to make us wait the next time */
575 	g->recv.pkt.hdr.cmd = DSrMsg_ok;
576 	return returned_ptid;
577 }
578 
qnxr_set_bp(libqnxr_t * g,ut64 address,const char * conditions)579 int qnxr_set_bp (libqnxr_t *g, ut64 address, const char *conditions) {
580 	return _qnxr_set_bp (g, address, conditions, BREAKPOINT);
581 }
582 
qnxr_set_hwbp(libqnxr_t * g,ut64 address,const char * conditions)583 int qnxr_set_hwbp (libqnxr_t *g, ut64 address, const char *conditions) {
584 	return _qnxr_set_bp (g, address, conditions, HARDWARE_BREAKPOINT);
585 }
586 
qnxr_remove_bp(libqnxr_t * g,ut64 address)587 int qnxr_remove_bp (libqnxr_t *g, ut64 address) {
588 	return _qnxr_remove_bp (g, address, BREAKPOINT);
589 }
590 
qnxr_remove_hwbp(libqnxr_t * g,ut64 address)591 int qnxr_remove_hwbp (libqnxr_t *g, ut64 address) {
592 	return _qnxr_remove_bp (g, address, HARDWARE_BREAKPOINT);
593 }
594 
_qnxr_set_bp(libqnxr_t * g,ut64 address,const char * conditions,enum Breakpoint type)595 int _qnxr_set_bp (libqnxr_t *g, ut64 address, const char *conditions, enum Breakpoint type) {
596 	if (!g) return -1;
597 
598 	nto_send_init (g, DStMsg_brk, DSMSG_BRK_EXEC, SET_CHANNEL_DEBUG);
599 	g->tran.pkt.brk.addr = EXTRACT_UNSIGNED_INTEGER (&address, 4);
600 	g->tran.pkt.brk.size = 0;
601 	nto_send (g, sizeof (g->tran.pkt.brk), 0);
602 
603 	if (g->recv.pkt.hdr.cmd == DSrMsg_err)
604 		return -1;
605 	return 0;
606 }
607 
_qnxr_remove_bp(libqnxr_t * g,ut64 address,enum Breakpoint type)608 int _qnxr_remove_bp (libqnxr_t *g, ut64 address, enum Breakpoint type) {
609 	if (!g) return -1;
610 
611 	nto_send_init (g, DStMsg_brk, DSMSG_BRK_EXEC, SET_CHANNEL_DEBUG);
612 	g->tran.pkt.brk.addr = EXTRACT_UNSIGNED_INTEGER (&address, 4);
613 	g->tran.pkt.brk.size = -1;
614 	nto_send (g, sizeof (g->tran.pkt.brk), 0);
615 
616 	if (g->recv.pkt.hdr.cmd == DSrMsg_err)
617 		return -1;
618 	return 0;
619 }
620 
nto_send_init(libqnxr_t * g,ut32 cmd,ut32 subcmd,ut32 chan)621 void nto_send_init (libqnxr_t *g, ut32 cmd, ut32 subcmd, ut32 chan) {
622 	g->tran.pkt.hdr.cmd = cmd;
623 	g->tran.pkt.hdr.subcmd = subcmd;
624 	g->tran.pkt.hdr.mid = ((chan == SET_CHANNEL_DEBUG) ? g->mid++ : 0);
625 	g->tran.pkt.hdr.channel = chan;
626 }
627 
nto_parse_notify(libqnxr_t * g)628 ptid_t nto_parse_notify (libqnxr_t *g) {
629 	pid_t pid, tid;
630 
631 	pid = EXTRACT_SIGNED_INTEGER (&g->recv.pkt.notify.pid, 4);
632 	tid = EXTRACT_SIGNED_INTEGER (&g->recv.pkt.notify.tid, 4);
633 
634 	if (tid == 0) tid = 1;
635 	eprintf ("%s: parse notify %d\n", __func__, g->recv.pkt.hdr.subcmd);
636 
637 	switch (g->recv.pkt.hdr.subcmd) {
638 	case DSMSG_NOTIFY_PIDUNLOAD:
639 		g->notify_type = R_DEBUG_REASON_DEAD;
640 		break;
641 	case DSMSG_NOTIFY_BRK:
642 		g->stop_flags = EXTRACT_UNSIGNED_INTEGER (&g->recv.pkt.notify.un.brk.flags, 4);
643 		g->stop_pc = EXTRACT_UNSIGNED_INTEGER (&g->recv.pkt.notify.un.brk.ip, 4);
644 		g->notify_type = R_DEBUG_REASON_BREAKPOINT;
645 		break;
646 	case DSMSG_NOTIFY_STEP:
647 		g->notify_type = R_DEBUG_REASON_STEP;
648 		break;
649 	case DSMSG_NOTIFY_SIGEV:
650 		g->notify_type = R_DEBUG_REASON_SIGNAL;
651 		g->signal = host_signal_from_nto (EXTRACT_SIGNED_INTEGER (&g->recv.pkt.notify.un.sigev.signo, 4));
652 		break;
653 	case DSMSG_NOTIFY_PIDLOAD:
654 		eprintf ("%s: notify type DSMSG_NOTIFY_PIDLOAD\n", __func__);
655 		g->notify_type = R_DEBUG_REASON_UNKNOWN;
656 		break;
657 	case DSMSG_NOTIFY_DLLLOAD:
658 	case DSMSG_NOTIFY_TIDLOAD:
659 	case DSMSG_NOTIFY_TIDUNLOAD:
660 	case DSMSG_NOTIFY_DLLUNLOAD:
661 		eprintf ("%s: notify type DSMSG_NOTIFY_DLLTID\n", __func__);
662 		g->notify_type = R_DEBUG_REASON_UNKNOWN;
663 		break;
664 	case DSMSG_NOTIFY_STOPPED:
665 		g->notify_type = R_DEBUG_REASON_SWI;
666 		break;
667 	default:
668 		eprintf ("%s: Unexpected notify type %d\n", __func__,
669 			 g->recv.pkt.hdr.subcmd);
670 		g->notify_type = R_DEBUG_REASON_UNKNOWN;
671 	}
672 
673 	return ptid_build (pid, tid);
674 }
675 
nto_send_env(libqnxr_t * g,const char * env)676 int nto_send_env (libqnxr_t *g, const char *env) {
677 	int len; /* Length including zero terminating char.  */
678 	int totlen = 0;
679 
680 	if (!g) return 0;
681 
682 	len = strlen (env) + 1;
683 	if (g->target_proto_minor >= 2) {
684 		while (len > DS_DATA_MAX_SIZE) {
685 			nto_send_init (g, DStMsg_env, DSMSG_ENV_SETENV_MORE,
686 				       SET_CHANNEL_DEBUG);
687 			memcpy (g->tran.pkt.env.data, env + totlen,
688 				DS_DATA_MAX_SIZE);
689 			if (!nto_send (g, offsetof (DStMsg_env_t, data) +
690 						  DS_DATA_MAX_SIZE,
691 				       1)) {
692 				/* An error occurred.  */
693 				return 0;
694 			}
695 			len -= DS_DATA_MAX_SIZE;
696 			totlen += DS_DATA_MAX_SIZE;
697 		}
698 	} else if (len > DS_DATA_MAX_SIZE) {
699 		/* Not supported by this protocol version.  */
700 		eprintf ("Protovers < 0.2 do not handle env vars longer than %d\n",
701 			 DS_DATA_MAX_SIZE - 1);
702 		return 0;
703 	}
704 	nto_send_init (g, DStMsg_env, DSMSG_ENV_SETENV, SET_CHANNEL_DEBUG);
705 	memcpy (g->tran.pkt.env.data, env + totlen, len);
706 	return nto_send (g, offsetof (DStMsg_env_t, data) + len, 1);
707 }
708 
nto_send_arg(libqnxr_t * g,const char * arg)709 int nto_send_arg (libqnxr_t *g, const char *arg) {
710 	int len;
711 
712 	if (!g) return 0;
713 
714 	len = strlen (arg) + 1;
715 	if (len > DS_DATA_MAX_SIZE - 4) {
716 		eprintf ("Argument too long: %.40s...\n", arg);
717 		return 0;
718 	}
719 	nto_send_init (g, DStMsg_env, DSMSG_ENV_ADDARG, SET_CHANNEL_DEBUG);
720 	memcpy (g->tran.pkt.env.data, arg, len);
721 	return nto_send (g, offsetof (DStMsg_env_t, data) + len, 1);
722 }
723 
nto_send(libqnxr_t * g,ut32 len,st32 report_errors)724 int nto_send (libqnxr_t *g, ut32 len, st32 report_errors) {
725 	int rlen;
726 	ut8 tries = 0;
727 
728 	if (!g || g->connected == 0) {
729 		return -1;
730 	}
731 	g->send_len = len;
732 	for (tries = 0;; tries++) {
733 		if (tries >= MAX_TRAN_TRIES) {
734 			eprintf ("%s: Remote exhausted %d retries.\n", __func__, tries);
735 			return -1;
736 		}
737 		qnxr_send_packet (g);
738 		for (;;) {
739 			rlen = qnxr_read_packet (g);
740 			if ((g->channelrd != SET_CHANNEL_TEXT) || (rlen == -1))
741 				break;
742 			//nto_incoming_text (rlen); TODO
743 		}
744 		if (rlen == -1) {
745 			eprintf ("%s: NAK received - resending\n", __func__);
746 			continue;
747 		}
748 		if ((rlen >= 0) && (g->recv.pkt.hdr.mid == g->tran.pkt.hdr.mid))
749 			break;
750 		eprintf ("%s: mid mismatch: %d/%d\n", __func__, g->recv.pkt.hdr.mid,
751 			 g->tran.pkt.hdr.mid);
752 	}
753 
754 	switch (g->channelrd) {
755 	case SET_CHANNEL_DEBUG:
756 		g->recv.pkt.hdr.cmd &= ~DSHDR_MSG_BIG_ENDIAN;
757 		if (g->recv.pkt.hdr.cmd == DSrMsg_err) {
758 			if (report_errors) {
759 				int nerrno = errnoconvert (
760 					EXTRACT_SIGNED_INTEGER (&g->recv.pkt.err.err, 4));
761 				switch (g->recv.pkt.hdr.subcmd) {
762 				case PDEBUG_ENOERR:
763 					eprintf ("remote: error packet with errno %d\n", nerrno);
764 					break;
765 				case PDEBUG_ENOPTY:
766 					eprintf ("remote: no ptys available\n");
767 					break;
768 				case PDEBUG_ETHREAD:
769 					eprintf ("remote: thread start error\n");
770 					break;
771 				case PDEBUG_ECONINV:
772 					eprintf ("remote: invalid console number\n");
773 					break;
774 				case PDEBUG_ESPAWN:
775 					eprintf ("Remote (spawn error)\n");
776 					break;
777 				case PDEBUG_EPROCFS:
778 					eprintf ("Remote (procfs [/proc] error)\n");
779 					break;
780 				case PDEBUG_EPROCSTOP:
781 					eprintf ("Remote (devctl PROC_STOP error)\n");
782 					break;
783 				case PDEBUG_EQPSINFO:
784 					eprintf ("Remote (psinfo error)\n");
785 					break;
786 				case PDEBUG_EQMEMMODEL:
787 					eprintf ("Remote (invalid memory model [not flat])\n");
788 					break;
789 				case PDEBUG_EQPROXY:
790 					eprintf ("Remote (proxy error)\n");
791 					break;
792 				case PDEBUG_EQDBG:
793 					eprintf ("Remote (__nto_debug_* error)\n");
794 					break;
795 				default:
796 					eprintf ("Remote error\n");
797 				}
798 			}
799 		}
800 		break;
801 	case SET_CHANNEL_TEXT:
802 	case SET_CHANNEL_RESET:
803 		break;
804 	}
805 	return rlen;
806 }
807