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