Rizin
unix-like reverse engineering framework and cli tools
core.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2014-2018 defragger <rlaemmert@gmail.com>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include "gdbclient/responses.h"
5 #include "gdbclient/commands.h"
6 #include "gdbclient/core.h"
7 #include "gdbclient/xml.h"
8 #include "arch.h"
9 #include "libgdbr.h"
10 #include "gdbr_common.h"
11 #include "packet.h"
12 #include "rz_util/rz_strbuf.h"
13 #include "rz_cons.h"
14 #include "rz_debug.h"
15 
16 #if __UNIX__
17 #include <errno.h>
18 #include <fcntl.h>
19 #include <string.h>
20 #include <termios.h>
21 #endif
22 
23 #if __UNIX__
24 #include <signal.h>
25 #endif
26 
27 #include <assert.h>
28 
29 #define QSUPPORTED_MAX_RETRIES 5
30 
31 extern char hex2char(char *hex);
32 
33 #if 0
34 static int set_interface_attribs(int fd, int speed, int parity) {
35 #if defined(_MSC_VER) || defined(__MINGW32__)
36 #pragma message("gdbclient/core.c: set_interface_attribs not implemented")
37 #else
38  struct termios tty;
39  memset (&tty, 0, sizeof tty);
40  if (tcgetattr (fd, &tty) != 0) {
41  return -1;
42  }
43 
44  cfsetospeed (&tty, speed);
45  cfsetispeed (&tty, speed);
46 
47  tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; // 8-bit chars
48  // disable IGNBRK for mismatched speed tests; otherwise receive break
49  // as \000 chars
50  tty.c_iflag &= ~IGNBRK; // disable break processing
51  tty.c_lflag = 0; // no signaling chars, no echo,
52  // no canonical processing
53  tty.c_oflag = 0; // no remapping, no delays
54  tty.c_cc[VMIN] = 0; // read doesn't block
55  tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
56 
57  tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl
58 
59  tty.c_cflag |= (CLOCAL | CREAD);// ignore modem controls,
60  // enable reading
61  tty.c_cflag &= ~(PARENB | PARODD); // shut off parity
62  tty.c_cflag |= parity;
63  tty.c_cflag &= ~CSTOPB;
64  tty.c_cflag &= ~CRTSCTS;
65 
66  if (tcsetattr (fd, TCSANOW, &tty) != 0) {
67  return -1;
68  }
69 #endif
70  return 0;
71 }
72 #endif
73 
74 static struct {
75  ut8 *buf;
77  bool valid, init;
79 
80 static void reg_cache_init(libgdbr_t *g) {
81  reg_cache.maxlen = g->data_max;
82  reg_cache.buflen = 0;
83  reg_cache.valid = false;
84  reg_cache.init = false;
85  if ((reg_cache.buf = malloc(reg_cache.maxlen))) {
86  reg_cache.init = true;
87  }
88 }
89 
90 static void gdbr_break_process(void *arg) {
91  libgdbr_t *g = (libgdbr_t *)arg;
92  (void)g;
93  g->isbreaked = true;
94 }
95 
97  if (!rz_th_lock_tryenter(g->gdbr_lock)) {
98  return false;
99  }
100  g->gdbr_lock_depth++;
102  return true;
103 }
104 
107  void *bed = rz_cons_sleep_begin();
108  rz_th_lock_enter(g->gdbr_lock);
109  g->gdbr_lock_depth++;
110  rz_cons_sleep_end(bed);
111  if (g->isbreaked) {
112  return false;
113  }
114  return true;
115 }
116 
119  assert(g->gdbr_lock_depth > 0);
120  bool last_leave = g->gdbr_lock_depth == 1;
121  g->gdbr_lock_depth--;
122  rz_th_lock_leave(g->gdbr_lock);
123  // if this is the last lock this thread holds make sure that we disable the break
124  if (last_leave) {
125  g->isbreaked = false;
126  }
127 }
128 
130  int ret = -1;
131  if (!gdbr_lock_enter(g)) {
132  goto end;
133  }
134  reg_cache_init(g);
135  if (g->stub_features.qXfer_features_read) {
137  }
138  // Check if 'g' packet is supported
139  if (send_msg(g, "g") < 0 || read_packet(g, false) < 0 || send_ack(g) < 0) {
140  ret = -1;
141  goto end;
142  }
143  if (g->data_len == 0 || (g->data_len == 3 && g->data[0] == 'E')) {
144  ret = -1;
145  goto end;
146  }
147  g->stub_features.lldb.g = true;
148 
149  ret = 0;
150 end:
152  return ret;
153 }
154 
155 int gdbr_connect(libgdbr_t *g, const char *host, int port) {
156  const char *message = "qSupported:multiprocess+;qRelocInsn+;xmlRegisters=i386";
157  int i;
158  int ret = -1;
159  void *bed = NULL;
160 
161  if (!g || !host) {
162  return -1;
163  }
164  if (!gdbr_lock_enter(g)) {
165  goto end;
166  }
167  // Initial max_packet_size for remote target (minimum so far for AVR = 64)
168  g->stub_features.pkt_sz = 64;
169  char *env_pktsz_str;
170  ut32 env_pktsz = 0;
171  if ((env_pktsz_str = rz_sys_getenv("RZ_GDB_PKTSZ"))) {
172  if ((env_pktsz = (ut32)strtoul(env_pktsz_str, NULL, 10))) {
173  g->stub_features.pkt_sz = RZ_MAX(env_pktsz, GDB_MAX_PKTSZ);
174  }
175  }
176  // Use the default break handler for rz_socket_connect to send a signal
178  bed = rz_cons_sleep_begin();
179  if (*host == '/') {
180  ret = rz_socket_connect_serial(g->sock, host, port, 1);
181  } else {
182  ret = rz_socket_connect_tcp(g->sock, host, sdb_fmt("%d", port), 1);
183  }
184  rz_cons_sleep_end(bed);
186  if (!ret) {
187  ret = -1;
188  goto end;
189  }
190  if ((ret = send_ack(g)) < 0) {
191  goto end;
192  }
193  read_packet(g, true); // vcont=true lets us skip if we get no reply
194  g->connected = 1;
195  bed = rz_cons_sleep_begin();
196  // TODO add config possibility here
197  for (i = 0; i < QSUPPORTED_MAX_RETRIES && !g->isbreaked; i++) {
198  ret = send_msg(g, message);
199  if (ret < 0) {
200  continue;
201  }
202  ret = read_packet(g, false);
203  if (ret < 0) {
204  continue;
205  }
206  ret = handle_qSupported(g);
207  if (ret < 0) {
208  continue;
209  }
210  break;
211  }
212  rz_cons_sleep_end(bed);
213  if (g->isbreaked) {
214  g->isbreaked = false;
215  ret = -1;
216  goto end;
217  }
218  if (ret < 0) {
219  goto end;
220  }
221  if (env_pktsz > 0) {
222  g->stub_features.pkt_sz = RZ_MAX(RZ_MIN(env_pktsz, g->stub_features.pkt_sz), GDB_MAX_PKTSZ);
223  }
224  // If no-ack supported, enable no-ack mode (should speed up things)
225  if (g->stub_features.QStartNoAckMode) {
226  if ((ret = send_msg(g, "QStartNoAckMode")) < 0) {
227  goto end;
228  }
229  read_packet(g, false);
230  if (!strncmp(g->data, "OK", 2)) {
231  // Just in case, send ack
232  send_ack(g);
233  g->no_ack = true;
234  }
235  }
236  if (g->remote_type == GDB_REMOTE_TYPE_LLDB) {
237  if ((ret = gdbr_connect_lldb(g)) < 0) {
238  goto end;
239  }
240  }
241  // Query the thread / process id
242  g->stub_features.qC = true;
243  g->pid = g->tid = 0;
244  if ((ret = send_msg(g, "qC")) < 0) {
245  goto end;
246  }
247  read_packet(g, false);
248  if (handle_qC(g) < 0) {
249  g->stub_features.qC = false;
250  }
251  // Check if vCont is supported
253  // Set pid/thread for operations other than "step" and "continue"
254  if (gdbr_select(g, g->pid, g->tid) < 0) {
255  // return -1;
256  }
257  // Set thread for "step" and "continue" operations
258  if ((ret = send_msg(g, "Hc-1")) < 0) {
259  goto end;
260  }
261  read_packet(g, false);
262  ret = send_ack(g);
263  if (ret < 0) {
264  goto end;
265  }
266  if (strcmp(g->data, "OK")) {
267  // return -1;
268  }
269  if (g->stub_features.qXfer_features_read) {
271  }
272  reg_cache_init(g);
273 
274  ret = 0;
275 end:
276  if (ret != 0) {
277  rz_socket_close(g->sock);
278  }
280  return ret;
281 }
282 
284  // TODO Disconnect maybe send something to gdbserver
285  if (!g || !rz_socket_close(g->sock)) {
286  return -1;
287  }
288  if (!gdbr_lock_enter(g)) {
289  goto end;
290  }
291  reg_cache.valid = false;
292  g->stop_reason.is_valid = false;
293  free(reg_cache.buf);
294  if (g->target.valid) {
295  free(g->target.regprofile);
296  free(g->registers);
297  }
298  g->connected = 0;
299 end:
301  return 0;
302 }
303 
304 int gdbr_select(libgdbr_t *g, int pid, int tid) {
305  char cmd[64] = { 0 };
306  int ret = -1;
307 
308  if (!gdbr_lock_enter(g)) {
309  goto end;
310  }
311  reg_cache.valid = false;
312  g->pid = pid;
313  g->tid = tid;
314  strcpy(cmd, "Hg");
315  if ((ret = write_thread_id(cmd + 2, sizeof(cmd) - 3, pid, tid,
316  g->stub_features.multiprocess)) < 0) {
317  goto end;
318  }
319  g->stop_reason.is_valid = false;
320  if (send_msg(g, cmd) < 0 || read_packet(g, false) < 0 || send_ack(g) < 0) {
321  ret = -1;
322  goto end;
323  }
324  if (strcmp(g->data, "OK")) {
325  ret = -1;
326  goto end;
327  }
328 
329  ret = 0;
330 end:
332  return ret;
333 }
334 
336  int ret = -1;
337  char *ptr = NULL;
338 
339  if (!g) {
340  return -1;
341  }
342 
343  if (!gdbr_lock_enter(g)) {
344  goto end;
345  }
346  if (send_msg(g, "vCont?") < 0 || read_packet(g, false) < 0 || send_ack(g) < 0) {
347  ret = -1;
348  goto end;
349  }
350  if (g->data_len == 0) {
351  g->stub_features.vContSupported = false;
352  ret = 0;
353  goto end;
354  }
355  g->data[g->data_len] = '\0';
356  if (!(ptr = strtok(g->data + strlen("vCont;"), ";"))) {
357  ret = 0;
358  goto end;
359  }
360  while (ptr) {
361  switch (*ptr) {
362  case 's':
363  g->stub_features.vcont.s = true;
364  break;
365  case 'S':
366  g->stub_features.vcont.S = true;
367  break;
368  case 'c':
369  g->stub_features.vcont.c = true;
370  break;
371  case 'C':
372  g->stub_features.vcont.C = true;
373  break;
374  case 't':
375  g->stub_features.vcont.t = true;
376  break;
377  case 'r':
378  g->stub_features.vcont.r = true;
379  break;
380  }
381  g->stub_features.vContSupported = true;
382  ptr = strtok(NULL, ";");
383  }
384 
385  ret = 0;
386 end:
388  return ret;
389 }
390 
392  int ret = -1;
393  if (!gdbr_lock_enter(g)) {
394  goto end;
395  }
396  if (!g || send_msg(g, "?") < 0 || read_packet(g, false) < 0) {
397  ret = -1;
398  goto end;
399  }
400  ret = handle_stop_reason(g);
401 end:
403  return ret;
404 }
405 
407  int ret = -1;
408 
409  if (!gdbr_lock_enter(g)) {
410  goto end;
411  }
412  g->stop_reason.is_valid = false;
413  reg_cache.valid = false;
414  // Activate extended mode if possible.
415  ret = send_msg(g, "!");
416  if (ret < 0) {
417  g->stub_features.extended_mode = 0;
418  goto end;
419  }
420  read_packet(g, false);
421  ret = send_ack(g);
422  if (ret < 0) {
423  g->stub_features.extended_mode = 0;
424  goto end;
425  }
426  if (strncmp(g->data, "OK", 2)) {
427  g->stub_features.extended_mode = 0;
428  ret = -1;
429  goto end;
430  }
431  g->stub_features.extended_mode = 1;
432 
433  ret = 0;
434 end:
436  return ret;
437 }
438 
440  int ret = -1;
441  char *cmd = NULL;
442  size_t buffer_size;
443 
444  if (!g || !g->sock) {
445  return -1;
446  }
447 
448  if (!gdbr_lock_enter(g)) {
449  goto end;
450  }
451  g->stop_reason.is_valid = false;
452  reg_cache.valid = false;
453 
454  if (g->stub_features.extended_mode == -1) {
456  }
457 
458  if (!g->stub_features.extended_mode) {
459  // vAttach needs extended mode to do anything.
460  ret = -2;
461  goto end;
462  }
463 
464  buffer_size = strlen(CMD_ATTACH) + (sizeof(int) * 2) + 1;
465  cmd = calloc(buffer_size, sizeof(char));
466  if (!cmd) {
467  ret = -1;
468  goto end;
469  }
470 
471  ret = snprintf(cmd, buffer_size, "%s%x", CMD_ATTACH, pid);
472  if (ret < 0) {
473  goto end;
474  }
475 
476  ret = send_msg(g, cmd);
477  if (ret < 0) {
478  goto end;
479  }
480 
481  if (read_packet(g, false) < 0) {
482  ret = -1;
483  goto end;
484  }
485 
486  ret = handle_attach(g);
487 end:
488  if (cmd) {
489  free(cmd);
490  }
492  return ret;
493 }
494 
496  int ret = -1;
497 
498  if (!g || !g->sock) {
499  return -1;
500  }
501 
502  if (!gdbr_lock_enter(g)) {
503  goto end;
504  }
505 
506  reg_cache.valid = false;
507  g->stop_reason.is_valid = false;
508  ret = send_msg(g, "D");
509  if (ret < 0) {
510  ret = -1;
511  goto end;
512  }
513  // Disconnect
514  ret = gdbr_disconnect(g);
515 end:
517  return ret;
518 }
519 
521  char *cmd = NULL;
522  int ret = -1;
523  size_t buffer_size;
524 
525  if (!g || !g->sock || !g->stub_features.multiprocess) {
526  return -1;
527  }
528 
529  if (!gdbr_lock_enter(g)) {
530  goto end;
531  }
532 
533  reg_cache.valid = false;
534  g->stop_reason.is_valid = false;
535 
536  buffer_size = strlen(CMD_DETACH_MP) + (sizeof(pid) * 2) + 1;
537  cmd = calloc(buffer_size, sizeof(char));
538  if (!cmd) {
539  ret = -1;
540  goto end;
541  }
542 
543  if ((snprintf(cmd, buffer_size, "%s%x", CMD_DETACH_MP, g->pid)) < 0) {
544  ret = -1;
545  goto end;
546  }
547 
548  ret = send_msg(g, cmd);
549  if (ret < 0) {
550  goto end;
551  }
552 
553  read_packet(g, false);
554  if ((ret = send_ack(g)) < 0) {
555  goto end;
556  }
557 
558  if (strncmp(g->data, "OK", 2)) {
559  ret = -1;
560  goto end;
561  }
562 
563  ret = 0;
564 end:
565  if (cmd) {
566  free(cmd);
567  }
569  return ret;
570 }
571 
573  int ret = -1;
574 
575  if (!g || !g->sock) {
576  return -1;
577  }
578 
579  if (!gdbr_lock_enter(g)) {
580  goto end;
581  }
582 
583  reg_cache.valid = false;
584  g->stop_reason.is_valid = false;
585 
586  if (g->stub_features.multiprocess) {
587  if (g->pid <= 0) {
588  ret = -1;
589  goto end;
590  }
591  ret = gdbr_kill_pid(g, g->pid);
592  goto end;
593  }
594 
595  if ((ret = send_msg(g, "k")) < 0) {
596  goto end;
597  }
598 
599  ret = 0;
600 end:
602  return ret;
603 }
604 
606  char *cmd = NULL;
607  int ret = -1;
608  size_t buffer_size;
609 
610  if (!g || !g->sock || !g->stub_features.multiprocess) {
611  return -1;
612  }
613 
614  if (!gdbr_lock_enter(g)) {
615  goto end;
616  }
617 
618  reg_cache.valid = false;
619  g->stop_reason.is_valid = false;
620 
621  buffer_size = strlen(CMD_KILL_MP) + (sizeof(pid) * 2) + 1;
622  cmd = calloc(buffer_size, sizeof(char));
623  if (!cmd) {
624  ret = -1;
625  goto end;
626  }
627 
628  if ((snprintf(cmd, buffer_size, "%s%x", CMD_KILL_MP, g->pid)) < 0) {
629  ret = -1;
630  goto end;
631  }
632  if ((ret = send_msg(g, cmd)) < 0) {
633  goto end;
634  }
635 
636  read_packet(g, false);
637  if ((ret = send_ack(g)) < 0) {
638  goto end;
639  }
640  if (strncmp(g->data, "OK", 2)) {
641  ret = -1;
642  goto end;
643  }
644 
645 end:
646  if (cmd) {
647  free(cmd);
648  }
650  return ret;
651 }
652 
654  // Send the stop reply query packet and get register info
655  // (this is what lldb does)
656  int ret = -1;
657 
658  if (!g || !g->sock) {
659  return -1;
660  }
661 
662  if (!gdbr_lock_enter(g)) {
663  goto end;
664  }
665 
666  if (send_msg(g, "?") < 0 || read_packet(g, false) < 0) {
667  ret = -1;
668  goto end;
669  }
670  if ((ret = handle_lldb_read_reg(g)) < 0) {
671  goto end;
672  }
673  if (reg_cache.init) {
674  reg_cache.buflen = g->data_len;
675  memcpy(reg_cache.buf, g->data, reg_cache.buflen);
676  reg_cache.valid = true;
677  }
678 
679  ret = 0;
680 end:
682  return ret;
683 }
684 
686  int ret = -1;
687 
688  if (!g || !g->data) {
689  return -1;
690  }
691  if (reg_cache.init && reg_cache.valid) {
692  g->data_len = reg_cache.buflen;
693  memcpy(g->data, reg_cache.buf, reg_cache.buflen);
694  return 0;
695  }
696  // Don't wait on the lock in read_registers since it's frequently called, including
697  // each time "enter" is pressed. Otherwise the user will be forced to interrupt exit
698  // read_registers constantly while another task is in progress
699  if (!gdbr_lock_tryenter(g)) {
700  return -1;
701  }
702 
703  if (g->remote_type == GDB_REMOTE_TYPE_LLDB && !g->stub_features.lldb.g) {
705  goto end;
706  }
707  if ((ret = send_msg(g, CMD_READREGS)) < 0) {
708  goto end;
709  }
710  if (read_packet(g, false) < 0 || handle_g(g) < 0) {
711  ret = -1;
712  goto end;
713  }
714  if (reg_cache.init) {
715  reg_cache.buflen = g->data_len;
716  memset(reg_cache.buf, 0, reg_cache.buflen);
717  memcpy(reg_cache.buf, g->data, reg_cache.buflen);
718  reg_cache.valid = true;
719  }
720 
721  ret = 0;
722 end:
724  return ret;
725 }
726 
727 static int gdbr_read_memory_page(libgdbr_t *g, ut64 address, ut8 *buf, int len) {
728  char command[128] = { 0 };
729  int last, ret_len, pkt;
730  ret_len = 0;
731 
732  if (!g) {
733  return -1;
734  }
735  if (len < 1) {
736  return len;
737  }
738 
739  if (!gdbr_lock_enter(g)) {
740  goto end;
741  }
742 
743  g->stub_features.pkt_sz = RZ_MAX(g->stub_features.pkt_sz, GDB_MAX_PKTSZ);
744  int data_sz = g->stub_features.pkt_sz / 2;
745  int num_pkts = len / data_sz;
746  last = len % data_sz;
747  ret_len = 0;
748  for (pkt = 0; pkt < num_pkts; pkt++) {
749  if (snprintf(command, sizeof(command) - 1,
750  "%s%" PFMT64x ",%" PFMT64x, CMD_READMEM,
751  (ut64)address + (pkt * data_sz),
752  (ut64)data_sz) < 0) {
753  ret_len = -1;
754  goto end;
755  }
756  if (send_msg(g, command) < 0) {
757  ret_len = -1;
758  goto end;
759  }
760  if (read_packet(g, false) < 0) {
761  ret_len = -1;
762  goto end;
763  }
764  if (handle_m(g) < 0) {
765  ret_len = -1;
766  goto end;
767  }
768  int delta = (pkt * data_sz);
769 
770  if (delta > len) {
771  eprintf("oops\n");
772  break;
773  }
774  int left = RZ_MIN(g->data_len, len - delta);
775  if (left > 0) {
776  memcpy(buf + delta, g->data, left);
777  ret_len += g->data_len;
778  }
779  }
780  if (last) {
781  if (snprintf(command, sizeof(command) - 1,
782  "%s%016" PFMT64x ",%" PFMT64x, CMD_READMEM,
783  (ut64)(address + (num_pkts * data_sz)),
784  (ut64)last) < 0) {
785  ret_len = -1;
786  goto end;
787  }
788  if (send_msg(g, command) < 0) {
789  ret_len = -1;
790  goto end;
791  }
792  if (read_packet(g, false) < 0) {
793  ret_len = -1;
794  goto end;
795  }
796  if (handle_m(g) < 0) {
797  ret_len = -1;
798  goto end;
799  }
800  int delta = num_pkts * data_sz;
801  int left = RZ_MIN(g->data_len, len - delta);
802  if (left > 0) {
803  memcpy(buf + delta, g->data, left);
804  ret_len += g->data_len;
805  }
806  }
807 end:
809  return ret_len;
810 }
811 
812 int gdbr_read_memory(libgdbr_t *g, ut64 address, ut8 *buf, int len) {
813  int ret_len, ret, tmp;
814  int page_size = g->page_size;
815  ret_len = 0;
816 
817  if (!gdbr_lock_enter(g)) {
818  goto end;
819  }
820 
821  // Read and round up to page size
822  tmp = page_size - (address & (page_size - 1));
823  if (tmp >= len) {
824  ret_len = gdbr_read_memory_page(g, address, buf, len);
825  goto end;
826  }
827  if ((ret = gdbr_read_memory_page(g, address, buf, tmp)) != tmp) {
828  ret_len = ret;
829  goto end;
830  }
831  len -= tmp;
832  address += tmp;
833  buf += tmp;
834  ret_len += ret;
835  // Read complete pages
836  while (len > page_size) {
837  if ((ret = gdbr_read_memory_page(g, address, buf, page_size)) != page_size) {
838  if (ret < 1) {
839  goto end;
840  }
841  ret_len += ret;
842  goto end;
843  }
844  len -= page_size;
845  address += page_size;
846  buf += page_size;
847  ret_len += page_size;
848  }
849  // Read left-overs
850  if ((ret = gdbr_read_memory_page(g, address, buf, len)) < 0) {
851  goto end;
852  }
853 
854  ret_len += ret;
855 end:
857  return ret_len;
858 }
859 
860 int gdbr_write_memory(libgdbr_t *g, ut64 address, const uint8_t *data, ut64 len) {
861  int ret = -1;
862  int command_len, pkt, max_cmd_len = 64;
863  ut64 num_pkts, last, data_sz;
864  char *tmp;
865  if (!g || !data) {
866  return -1;
867  }
868  g->stub_features.pkt_sz = RZ_MAX(g->stub_features.pkt_sz, GDB_MAX_PKTSZ);
869  data_sz = g->stub_features.pkt_sz / 2;
870  if (data_sz < 1) {
871  return -1;
872  }
873  num_pkts = len / data_sz;
874  last = len % data_sz;
875  if (!(tmp = calloc(max_cmd_len + g->stub_features.pkt_sz, sizeof(char)))) {
876  return -1;
877  }
878 
879  if (!gdbr_lock_enter(g)) {
880  goto end;
881  }
882 
883  for (pkt = num_pkts - 1; pkt >= 0; pkt--) {
884  if ((command_len = snprintf(tmp, max_cmd_len,
885  "%s%016" PFMT64x ",%" PFMT64x ":", CMD_WRITEMEM,
886  address + (pkt * data_sz), data_sz)) < 0) {
887  ret = -1;
888  goto end;
889  }
890  pack_hex((char *)data + (pkt * data_sz), data_sz, (tmp + command_len));
891  if ((ret = send_msg(g, tmp)) < 0) {
892  goto end;
893  }
894  if ((ret = read_packet(g, false)) < 0) {
895  goto end;
896  }
897  if ((ret = handle_M(g)) < 0) {
898  goto end;
899  }
900  }
901  if (last) {
902  if ((command_len = snprintf(tmp, max_cmd_len,
903  "%s%016" PFMT64x ",%" PFMT64x ":", CMD_WRITEMEM,
904  address + (num_pkts * data_sz), last)) < 0) {
905  ret = -1;
906  goto end;
907  }
908  pack_hex((char *)data + (num_pkts * data_sz), last, (tmp + command_len));
909  if ((ret = send_msg(g, tmp)) < 0) {
910  goto end;
911  }
912  if ((ret = read_packet(g, false)) < 0) {
913  goto end;
914  }
915  if ((ret = handle_M(g)) < 0) {
916  goto end;
917  }
918  }
919 
920  ret = 0;
921 end:
923  if (tmp) {
924  free(tmp);
925  }
926  return ret;
927 }
928 
929 int gdbr_step(libgdbr_t *g, int tid) {
930  int ret = -1;
931  char thread_id[64] = { 0 };
932 
933  if (!gdbr_lock_enter(g)) {
934  goto end;
935  }
936 
937  if (tid <= 0 || write_thread_id(thread_id, sizeof(thread_id) - 1, g->pid, tid, g->stub_features.multiprocess) < 0) {
938  send_vcont(g, "vCont?", NULL);
939  send_vcont(g, sdb_fmt("Hc%d", tid), NULL);
940  ret = send_vcont(g, CMD_C_STEP, NULL);
941  goto end;
942  }
943 
944  ret = send_vcont(g, CMD_C_STEP, thread_id);
945 end:
947  return ret;
948 }
949 
950 int gdbr_continue(libgdbr_t *g, int pid, int tid, int sig) {
951  char thread_id[64] = { 0 };
952  char command[16] = { 0 };
953  int ret = -1;
954 
955  if (!gdbr_lock_enter(g)) {
956  goto end;
957  }
958 
959  if (sig <= 0) {
960  strncpy(command, CMD_C_CONT, sizeof(command) - 1);
961  } else {
962  snprintf(command, sizeof(command) - 1, "%s%02x", CMD_C_CONT_SIG, sig);
963  }
964  if (tid <= 0 || write_thread_id(thread_id, sizeof(thread_id) - 1, g->pid, tid, g->stub_features.multiprocess) < 0) {
965  ret = send_vcont(g, command, NULL);
966  goto end;
967  }
968 
969  ret = send_vcont(g, command, thread_id);
970 end:
972  return ret;
973 }
974 
975 int gdbr_write_bin_registers(libgdbr_t *g, const char *regs, int len) {
976  int ret = -1;
977  uint64_t buffer_size = 0;
978  char *command = NULL;
979 
980  if (!g) {
981  return -1;
982  }
983 
984  if (!gdbr_lock_enter(g)) {
985  goto end;
986  }
987 
988  buffer_size = len * 2 + 8;
989  reg_cache.valid = false;
990 
991  command = calloc(buffer_size, sizeof(char));
992  if (!command) {
993  ret = -1;
994  goto end;
995  }
997  pack_hex(regs, len, command + 1);
998  if (send_msg(g, command) < 0) {
999  ret = -1;
1000  goto end;
1001  }
1002  if (read_packet(g, false) >= 0) {
1003  handle_G(g);
1004  } else {
1005  ret = -1;
1006  goto end;
1007  }
1008 
1009  ret = 0;
1010 end:
1011  gdbr_lock_leave(g);
1012  if (command) {
1013  free(command);
1014  }
1015  return ret;
1016 }
1017 
1018 int gdbr_write_register(libgdbr_t *g, int index, char *value, int len) {
1019  int ret = -1;
1020  char command[255] = { 0 };
1021  if (!g || !g->stub_features.P) {
1022  return -1;
1023  }
1024  if (!gdbr_lock_enter(g)) {
1025  goto end;
1026  }
1027 
1028  reg_cache.valid = false;
1029  ret = snprintf(command, sizeof(command) - 1, "%s%x=", CMD_WRITEREG, index);
1030  if (len + ret >= sizeof(command)) {
1031  eprintf("command is too small\n");
1032  ret = -1;
1033  goto end;
1034  }
1035  // Pad with zeroes
1036  memset(command + ret, atoi("0"), len);
1037  pack_hex(value, len, (command + ret));
1038  if (send_msg(g, command) < 0) {
1039  ret = -1;
1040  goto end;
1041  }
1042  if (read_packet(g, false) < 0 || handle_P(g) < 0) {
1043  ret = -1;
1044  goto end;
1045  }
1046  if (g->last_code == MSG_NOT_SUPPORTED) {
1047  g->stub_features.P = false;
1048  ret = -1;
1049  goto end;
1050  }
1051 
1052  ret = 0;
1053 end:
1054  gdbr_lock_leave(g);
1055  return ret;
1056 }
1057 
1058 int gdbr_write_reg(libgdbr_t *g, const char *name, char *value, int len) {
1059  int i = 0;
1060  int ret = -1;
1061  if (!g) {
1062  return -1;
1063  }
1064 
1065  if (!gdbr_lock_enter(g)) {
1066  goto end;
1067  }
1068 
1069  reg_cache.valid = false;
1070  while (g->registers[i].size > 0) {
1071  if (!strcmp(g->registers[i].name, name)) {
1072  break;
1073  }
1074  i++;
1075  }
1076  if (g->registers[i].size == 0) {
1077  eprintf("Error registername <%s> not found in profile\n", name);
1078  ret = -1;
1079  goto end;
1080  }
1081  if (g->stub_features.P && (ret = gdbr_write_register(g, i, value, len)) == 0) {
1082  goto end;
1083  }
1084 
1085  // Use 'G' if write_register failed/isn't supported
1087  memcpy(g->data + (g->registers[i].offset / 8), value, len);
1088  gdbr_write_bin_registers(g, g->data, g->data_len);
1089 
1090  ret = 0;
1091 end:
1092  gdbr_lock_leave(g);
1093  return ret;
1094 }
1095 
1096 int gdbr_write_registers(libgdbr_t *g, char *registers) {
1098  int i = 0;
1099  int ret = -1;
1100  unsigned int x, len;
1101  char *command, *reg, *buff, *value;
1102  // read current register set
1103 
1104  command = buff = value = NULL;
1105 
1106  if (!g) {
1107  return -1;
1108  }
1109 
1110  if (!gdbr_lock_enter(g)) {
1111  goto end;
1112  }
1113 
1115  reg_cache.valid = false;
1116  len = strlen(registers);
1117  buff = calloc(len, sizeof(char));
1118  if (!buff) {
1119  ret = -1;
1120  goto end;
1121  }
1122  memcpy(buff, registers, len);
1123  reg = strtok(buff, ",");
1124  while (reg) {
1125  char *name_end = strchr(reg, '=');
1126  if (name_end == NULL) {
1127  eprintf("Malformed argument: %s\n", reg);
1128  ret = -1;
1129  goto end;
1130  }
1131  *name_end = '\0'; // change '=' to '\0'
1132 
1133  // time to find the current register
1134  while (g->registers[i].size > 0) {
1135  if (strcmp(g->registers[i].name, reg) == 0) {
1136  const ut64 register_size = g->registers[i].size;
1137  const ut64 offset = g->registers[i].offset;
1138  value = calloc(register_size + 1, 2);
1139  if (!value) {
1140  ret = -1;
1141  goto end;
1142  }
1143 
1144  memset(value, '0', register_size * 2);
1145  name_end++;
1146  // be able to take hex with and without 0x
1147  if (name_end[1] == 'x' || name_end[1] == 'X') {
1148  name_end += 2;
1149  }
1150  const int val_len = strlen(name_end); // size of the rest
1151  strcpy(value + (register_size * 2 - val_len), name_end);
1152 
1153  for (x = 0; x < register_size; x++) {
1154  g->data[offset + register_size - x - 1] = hex2char(&value[x * 2]);
1155  }
1156  RZ_FREE(value);
1157  }
1158  i++;
1159  }
1160  reg = strtok(NULL, " ,");
1161  }
1162 
1163  buffer_size = g->data_len * 2 + 8;
1164  command = calloc(buffer_size, sizeof(char));
1165  if (!command) {
1166  ret = -1;
1167  goto end;
1168  }
1170  pack_hex(g->data, g->data_len, command + 1);
1171  ret = send_msg(g, command);
1172  if (ret < 0) {
1173  goto end;
1174  }
1175  read_packet(g, false);
1176  handle_G(g);
1177 
1178  ret = 0;
1179 end:
1180  if (command) {
1181  free(command);
1182  }
1183  if (buff) {
1184  free(buff);
1185  }
1186  if (value) {
1187  free(value);
1188  }
1189  gdbr_lock_leave(g);
1190  return ret;
1191 }
1192 
1193 int test_command(libgdbr_t *g, const char *command) {
1194  int ret = -1;
1195 
1196  if (!gdbr_lock_enter(g)) {
1197  goto end;
1198  }
1199 
1200  if ((ret = send_msg(g, command)) < 0) {
1201  goto end;
1202  }
1203  read_packet(g, false);
1204  hexdump(g->read_buff, g->data_len, 0);
1205 
1206  ret = 0;
1207 end:
1208  gdbr_lock_leave(g);
1209  return ret;
1210 }
1211 
1212 int send_vcont(libgdbr_t *g, const char *command, const char *thread_id) {
1213  char tmp[255] = { 0 };
1214  int ret = -1;
1215  void *bed = NULL;
1216 
1217  if (!g) {
1218  return -1;
1219  }
1220 
1221  if (!g->stub_features.vContSupported) {
1222  ret = snprintf(tmp, sizeof(tmp) - 1, "%s", command);
1223  } else {
1224  bool supported = false;
1225  switch (*command) {
1226  case 's':
1227  if (g->stub_features.vcont.s) {
1228  supported = true;
1229  }
1230  break;
1231  case 'S':
1232  if (g->stub_features.vcont.S) {
1233  supported = true;
1234  }
1235  break;
1236  case 'c':
1237  if (g->stub_features.vcont.c) {
1238  supported = true;
1239  }
1240  break;
1241  case 'C':
1242  if (g->stub_features.vcont.C) {
1243  supported = true;
1244  }
1245  break;
1246  case 't':
1247  if (g->stub_features.vcont.t) {
1248  supported = true;
1249  }
1250  break;
1251  case 'r':
1252  if (g->stub_features.vcont.r) {
1253  supported = true;
1254  }
1255  break;
1256  }
1257  if (supported) {
1258  if (!thread_id) {
1259  ret = snprintf(tmp, sizeof(tmp) - 1, "%s;%s", CMD_C, command);
1260  } else {
1261  ret = snprintf(tmp, sizeof(tmp) - 1, "%s;%s:%s", CMD_C, command, thread_id);
1262  }
1263  } else {
1264  ret = snprintf(tmp, sizeof(tmp) - 1, "%s", command);
1265  }
1266  }
1267  if (ret < 0) {
1268  return ret;
1269  }
1270 
1271  if (!gdbr_lock_enter(g)) {
1272  goto end;
1273  }
1274  reg_cache.valid = false;
1275  g->stop_reason.is_valid = false;
1276  ret = send_msg(g, tmp);
1277  if (ret < 0) {
1278  goto end;
1279  }
1280 
1281  bed = rz_cons_sleep_begin();
1282  while (read_packet(g, true) < 0 && !g->isbreaked && rz_socket_is_connected(g->sock))
1283  ;
1284  if (g->isbreaked) {
1285  g->isbreaked = false;
1286  // Stop target
1287  rz_socket_write(g->sock, "\x03", 1);
1288  // Read the stop reason
1289  if (read_packet(g, false) < 0) {
1290  ret = -1;
1291  goto end;
1292  }
1293  }
1294 
1295  ret = handle_cont(g);
1296 end:
1297  rz_cons_sleep_end(bed);
1298  gdbr_lock_leave(g);
1299  return ret;
1300 }
1301 
1302 int set_bp(libgdbr_t *g, ut64 address, const char *conditions, enum Breakpoint type, int sizebp) {
1303  char tmp[255] = { 0 };
1304  int ret = -1;
1305 
1306  if (!g) {
1307  return -1;
1308  }
1309 
1310  switch (type) {
1311  case BREAKPOINT:
1312  ret = snprintf(tmp, sizeof(tmp) - 1,
1313  "%s,%" PFMT64x ",%d", CMD_BP, address, sizebp);
1314  break;
1315  case HARDWARE_BREAKPOINT:
1316  ret = snprintf(tmp, sizeof(tmp) - 1,
1317  "%s,%" PFMT64x ",%d", CMD_HBP, address, sizebp);
1318  break;
1319  case WRITE_WATCHPOINT:
1320  ret = snprintf(tmp, sizeof(tmp) - 1,
1321  "%s,%" PFMT64x ",%d", CMD_HWW, address, sizebp);
1322  break;
1323  case READ_WATCHPOINT:
1324  ret = snprintf(tmp, sizeof(tmp) - 1,
1325  "%s,%" PFMT64x ",%d", CMD_HWR, address, sizebp);
1326  break;
1327  case ACCESS_WATCHPOINT:
1328  ret = snprintf(tmp, sizeof(tmp) - 1,
1329  "%s,%" PFMT64x ",%d", CMD_HWA, address, sizebp);
1330  break;
1331  default:
1332  break;
1333  }
1334  if (ret < 0) {
1335  return ret;
1336  }
1337 
1338  if (!gdbr_lock_enter(g)) {
1339  goto end;
1340  }
1341 
1342  g->stop_reason.is_valid = false;
1343  if ((ret = send_msg(g, tmp)) < 0) {
1344  goto end;
1345  }
1346 
1347  if ((ret = read_packet(g, false)) < 0) {
1348  goto end;
1349  }
1350 
1351  ret = handle_setbp(g);
1352 end:
1353  gdbr_lock_leave(g);
1354  return ret;
1355 }
1356 
1357 int gdbr_set_bp(libgdbr_t *g, ut64 address, const char *conditions, int sizebp) {
1358  return set_bp(g, address, conditions, BREAKPOINT, sizebp);
1359 }
1360 
1361 int gdbr_set_hwbp(libgdbr_t *g, ut64 address, const char *conditions, int sizebp) {
1362  return set_bp(g, address, conditions, HARDWARE_BREAKPOINT, sizebp);
1363 }
1364 
1365 int gdbr_set_hww(libgdbr_t *g, ut64 address, const char *conditions, int sizebp) {
1366  return set_bp(g, address, conditions, WRITE_WATCHPOINT, sizebp);
1367 }
1368 
1369 int gdbr_set_hwr(libgdbr_t *g, ut64 address, const char *conditions, int sizebp) {
1370  return set_bp(g, address, conditions, READ_WATCHPOINT, sizebp);
1371 }
1372 
1373 int gdbr_set_hwa(libgdbr_t *g, ut64 address, const char *conditions, int sizebp) {
1374  return set_bp(g, address, conditions, ACCESS_WATCHPOINT, sizebp);
1375 }
1376 
1377 int gdbr_remove_bp(libgdbr_t *g, ut64 address, int sizebp) {
1378  return remove_bp(g, address, BREAKPOINT, sizebp);
1379 }
1380 int gdbr_remove_hwbp(libgdbr_t *g, ut64 address, int sizebp) {
1381  return remove_bp(g, address, HARDWARE_BREAKPOINT, sizebp);
1382 }
1383 
1384 int gdbr_remove_hww(libgdbr_t *g, ut64 address, int sizebp) {
1385  return remove_bp(g, address, WRITE_WATCHPOINT, sizebp);
1386 }
1387 
1388 int gdbr_remove_hwr(libgdbr_t *g, ut64 address, int sizebp) {
1389  return remove_bp(g, address, READ_WATCHPOINT, sizebp);
1390 }
1391 
1392 int gdbr_remove_hwa(libgdbr_t *g, ut64 address, int sizebp) {
1393  return remove_bp(g, address, ACCESS_WATCHPOINT, sizebp);
1394 }
1395 
1396 int remove_bp(libgdbr_t *g, ut64 address, enum Breakpoint type, int sizebp) {
1397  char tmp[255] = { 0 };
1398  int ret = -1;
1399 
1400  if (!g) {
1401  return -1;
1402  }
1403 
1404  switch (type) {
1405  case BREAKPOINT:
1406  ret = snprintf(tmp, sizeof(tmp) - 1, "%s,%" PFMT64x ",%d", CMD_RBP, address, sizebp);
1407  break;
1408  case HARDWARE_BREAKPOINT:
1409  ret = snprintf(tmp, sizeof(tmp) - 1, "%s,%" PFMT64x ",%d", CMD_RHBP, address, sizebp);
1410  break;
1411  case WRITE_WATCHPOINT:
1412  ret = snprintf(tmp, sizeof(tmp) - 1, "%s,%" PFMT64x ",%d", CMD_RHWW, address, sizebp);
1413  break;
1414  case READ_WATCHPOINT:
1415  ret = snprintf(tmp, sizeof(tmp) - 1, "%s,%" PFMT64x ",%d", CMD_RHWR, address, sizebp);
1416  break;
1417  case ACCESS_WATCHPOINT:
1418  ret = snprintf(tmp, sizeof(tmp) - 1, "%s,%" PFMT64x ",%d", CMD_RHWA, address, sizebp);
1419  break;
1420  default:
1421  break;
1422  }
1423  if (ret < 0) {
1424  return ret;
1425  }
1426 
1427  if (!gdbr_lock_enter(g)) {
1428  goto end;
1429  }
1430 
1431  g->stop_reason.is_valid = false;
1432  if ((ret = send_msg(g, tmp)) < 0) {
1433  goto end;
1434  }
1435  if ((ret = read_packet(g, false)) < 0) {
1436  goto end;
1437  }
1438 
1439  ret = handle_removebp(g);
1440 end:
1441  gdbr_lock_leave(g);
1442  return ret;
1443 }
1444 
1445 int gdbr_open_file(libgdbr_t *g, const char *filename, int flags, int mode) {
1446  int ret = -1;
1447  char *buf;
1448  size_t buf_len;
1449 
1450  if (!g || !filename || !*filename) {
1451  return -1;
1452  }
1453  if (g->remote_file_fd >= 0) {
1454  eprintf("%s: Remote file already open\n", __func__);
1455  return -1;
1456  }
1457  buf_len = (strlen(filename) * 2) + strlen("vFile:open:") + 30;
1458  if (!(buf = calloc(buf_len, sizeof(char)))) {
1459  return -1;
1460  }
1461 
1462  if (!gdbr_lock_enter(g)) {
1463  goto end;
1464  }
1465  strcpy(buf, "vFile:open:");
1466  pack_hex(filename, strlen(filename), buf + strlen(buf));
1467  snprintf(buf + strlen(buf), buf_len - strlen(buf) - 1, ",%x,%x", flags, mode);
1468  if ((ret = send_msg(g, buf)) < 0) {
1469  goto end;
1470  }
1471  read_packet(g, false);
1472  if ((ret = handle_vFile_open(g)) < 0) {
1473  goto end;
1474  }
1475 
1476  ret = 0;
1477 end:
1478  if (buf) {
1479  free(buf);
1480  }
1481  gdbr_lock_leave(g);
1482  return ret;
1483 }
1484 
1485 int gdbr_read_file(libgdbr_t *g, ut8 *buf, ut64 max_len) {
1486  int ret, ret1;
1487  char command[64];
1488  ut64 data_sz;
1489  ret = 0;
1490  if (!g || !buf || !max_len) {
1491  return -1;
1492  }
1493  if (max_len >= INT32_MAX) {
1494  eprintf("%s: Too big a file read requested: %" PFMT64d, __func__, max_len);
1495  return -1;
1496  }
1497  if (g->remote_file_fd < 0) {
1498  eprintf("%s: No remote file opened\n", __func__);
1499  return -1;
1500  }
1501 
1502  if (!gdbr_lock_enter(g)) {
1503  goto end;
1504  }
1505  g->stub_features.pkt_sz = RZ_MAX(g->stub_features.pkt_sz, GDB_MAX_PKTSZ);
1506  data_sz = g->stub_features.pkt_sz / 2;
1507  ret = 0;
1508  while (ret < max_len) {
1509  if (snprintf(command, sizeof(command) - 1,
1510  "vFile:pread:%x,%" PFMT64x ",%" PFMT64x,
1511  (int)g->remote_file_fd, (ut64)RZ_MIN(data_sz, max_len - ret),
1512  (ut64)ret) < 0) {
1513  ret = -1;
1514  goto end;
1515  }
1516  if (send_msg(g, command) < 0) {
1517  ret = -1;
1518  goto end;
1519  }
1520  if (read_packet(g, false) < 0) {
1521  ret = -1;
1522  goto end;
1523  }
1524  if ((ret1 = handle_vFile_pread(g, buf + ret)) < 0) {
1525  ret = ret1;
1526  goto end;
1527  }
1528  if (ret1 == 0) {
1529  goto end;
1530  }
1531  ret += ret1;
1532  }
1533 
1534 end:
1535  gdbr_lock_leave(g);
1536  return ret;
1537 }
1538 
1540  int ret = -1;
1541  char buf[64];
1542 
1543  if (!g) {
1544  return -1;
1545  }
1546  if (g->remote_file_fd < 0) {
1547  eprintf("%s: No remote file opened\n", __func__);
1548  return -1;
1549  }
1550 
1551  if (!gdbr_lock_enter(g)) {
1552  goto end;
1553  }
1554  snprintf(buf, sizeof(buf) - 1, "vFile:close:%x", g->remote_file_fd);
1555  if ((ret = send_msg(g, buf)) < 0) {
1556  goto end;
1557  }
1558  read_packet(g, false);
1559  if ((ret = handle_vFile_close(g)) < 0) {
1560  goto end;
1561  }
1562  g->remote_file_fd = -1;
1563 
1564  ret = 0;
1565 end:
1566  gdbr_lock_leave(g);
1567  return ret;
1568 }
1569 
1571  reg_cache.valid = false;
1572 }
1573 
1574 int gdbr_send_qRcmd(libgdbr_t *g, const char *cmd, PrintfCallback cb_printf) {
1575  int ret = -1;
1576  char *buf;
1577  size_t len;
1578 
1579  if (!g || !cmd) {
1580  return -1;
1581  }
1582  len = strlen(cmd) * 2 + 8;
1583  if (!(buf = calloc(len, sizeof(char)))) {
1584  return -1;
1585  }
1586  strcpy(buf, "qRcmd,");
1587 
1588  if (!gdbr_lock_enter(g)) {
1589  goto end;
1590  }
1591  g->stop_reason.is_valid = false;
1592  reg_cache.valid = false;
1593  pack_hex(cmd, strlen(cmd), buf + 6);
1594  if ((ret = send_msg(g, buf)) < 0) {
1595  goto end;
1596  }
1597  if ((ret = read_packet(g, false)) < 0) {
1598  goto end;
1599  }
1600  while (1) {
1601  if ((ret = send_ack(g)) < 0) {
1602  goto end;
1603  }
1604  if (g->data_len == 0) {
1605  ret = -1;
1606  goto end;
1607  }
1608  if (g->data_len == 3 && g->data[0] == 'E' && isxdigit(g->data[1]) && isxdigit(g->data[2])) {
1609  ret = -1;
1610  goto end;
1611  }
1612  if (!strncmp(g->data, "OK", 2)) {
1613  break;
1614  }
1615  if (g->data[0] == 'O' && g->data_len % 2 == 1) {
1616  // Console output from gdbserver
1617  unpack_hex(g->data + 1, g->data_len - 1, g->data + 1);
1618  g->data[g->data_len - 1] = '\0';
1619  cb_printf("%s", g->data + 1);
1620  }
1621  if ((ret = read_packet(g, false)) < 0) {
1622  goto end;
1623  }
1624  }
1625 
1626  ret = 0;
1627 end:
1628  if (buf) {
1629  free(buf);
1630  }
1631  gdbr_lock_leave(g);
1632  return ret;
1633 }
1634 
1636  char msg[128], pidstr[16];
1637  char *path = NULL;
1638  ut64 len, off = 0;
1639  int ret = -1;
1640 
1641  if (!g) {
1642  return NULL;
1643  }
1644 
1645  len = g->stub_features.pkt_sz;
1646  memset(pidstr, 0, sizeof(pidstr));
1647  if (g->stub_features.multiprocess && pid > 0) {
1648  snprintf(pidstr, sizeof(pidstr), "%x", pid);
1649  }
1650 
1651  if (!gdbr_lock_enter(g)) {
1652  goto end;
1653  }
1654  while (1) {
1655  if (snprintf(msg, sizeof(msg) - 1,
1656  "qXfer:exec-file:read:%s:%" PFMT64x ",%" PFMT64x,
1657  pidstr, off, len) < 0) {
1658  ret = -1;
1659  goto end;
1660  }
1661  if (send_msg(g, msg) < 0 || read_packet(g, false) < 0 || send_ack(g) < 0 || g->data_len == 0) {
1662  ret = -1;
1663  goto end;
1664  }
1665  g->data[g->data_len] = '\0';
1666  if (g->data[0] == 'l') {
1667  if (g->data_len == 1) {
1668  break;
1669  }
1670  path = rz_str_append(path, g->data + 1);
1671  break;
1672  }
1673  if (g->data[0] != 'm') {
1674  ret = -1;
1675  goto end;
1676  }
1677  off += strlen(g->data + 1);
1678  if (!(path = rz_str_append(path, g->data + 1))) {
1679  ret = -1;
1680  goto end;
1681  }
1682  }
1683 
1684  ret = 0;
1685 end:
1686  gdbr_lock_leave(g);
1687  if (ret != 0) {
1688  if (path) {
1689  free(path);
1690  }
1691  return NULL;
1692  }
1693  return path;
1694 }
1695 
1696 bool gdbr_is_thread_dead(libgdbr_t *g, int pid, int tid) {
1697  bool ret = false;
1698 
1699  if (!g) {
1700  return false;
1701  }
1702  if (g->stub_features.multiprocess && pid <= 0) {
1703  return false;
1704  }
1705 
1706  if (!gdbr_lock_enter(g)) {
1707  goto end;
1708  }
1709  char msg[64] = { 0 }, thread_id[63] = { 0 };
1710  if (write_thread_id(thread_id, sizeof(thread_id) - 1, pid, tid,
1711  g->stub_features.multiprocess) < 0) {
1712  goto end;
1713  }
1714  if (snprintf(msg, sizeof(msg) - 1, "T%s", thread_id) < 0) {
1715  goto end;
1716  }
1717  if (send_msg(g, msg) < 0 || read_packet(g, false) < 0 || send_ack(g) < 0) {
1718  goto end;
1719  }
1720  if (g->data_len == 3 && g->data[0] == 'E') {
1721  ret = true;
1722  } else {
1723  ret = false;
1724  }
1725 
1726 end:
1727  gdbr_lock_leave(g);
1728  return ret;
1729 }
1730 
1732  int ret = -1;
1733  RzList *list = NULL;
1734  int tpid = -1, ttid = -1;
1735  char *ptr, *ptr2, *exec_file;
1736  RzDebugPid *dpid = NULL;
1737  RzListIter *iter = NULL;
1738 
1739  if (!g) {
1740  return NULL;
1741  }
1742 
1743  if (!gdbr_lock_enter(g)) {
1744  goto end;
1745  }
1746  if (!(list = rz_list_new())) {
1747  ret = -1;
1748  goto end;
1749  }
1750  // Use qfThreadInfo as a fallback since it doesn't actually show all children
1751  if (g->stub_features.qXfer_threads_read) {
1752  if (gdbr_read_processes_xml(g, pid, list) == 0) {
1753  ret = 0;
1754  goto end;
1755  }
1756  }
1757  // Child processes will only show up in ThreadInfo if gdbr is currently processing a
1758  // fork/vfork/exec event or if the children weren't detached yet. This is intended
1759  // gdb `info inferiors` behavior that can only be avoided using xml.
1760  eprintf("WARNING: Showing possibly incomplete pid list due to xml protocol failure\n");
1761 
1762  if (!g->stub_features.qXfer_exec_file_read || !(exec_file = gdbr_exec_file_read(g, pid))) {
1763  exec_file = "";
1764  }
1765  if (send_msg(g, "qfThreadInfo") < 0 || read_packet(g, false) < 0 || send_ack(g) < 0 || g->data_len == 0 || g->data[0] != 'm') {
1766  ret = -1;
1767  goto end;
1768  }
1769  while (1) {
1770  g->data[g->data_len] = '\0';
1771  ptr = g->data + 1;
1772  while (ptr) {
1773  if ((ptr2 = strchr(ptr, ','))) {
1774  *ptr2 = '\0';
1775  ptr2++;
1776  }
1777  if (read_thread_id(ptr, &tpid, &ttid, g->stub_features.multiprocess) < 0) {
1778  ptr = ptr2;
1779  continue;
1780  }
1781  // Avoid adding the same pid twice(could show more than once if it has threads)
1782  rz_list_foreach (list, iter, dpid) {
1783  if (tpid == dpid->pid) {
1784  continue;
1785  }
1786  }
1787  if (!(dpid = RZ_NEW0(RzDebugPid)) || !(dpid->path = strdup(exec_file))) {
1788  ret = -1;
1789  goto end;
1790  }
1791  dpid->pid = tpid;
1792  // If the pid isn't the debugged pid it must be a child pid
1793  if (tpid != g->pid) {
1794  dpid->ppid = g->pid;
1795  }
1796  dpid->uid = dpid->gid = -1;
1797  dpid->runnable = true;
1798  dpid->status = RZ_DBG_PROC_STOP;
1799  rz_list_append(list, dpid);
1800  ptr = ptr2;
1801  }
1802  if (send_msg(g, "qsThreadInfo") < 0 || read_packet(g, false) < 0 || send_ack(g) < 0 || g->data_len == 0 || (g->data[0] != 'm' && g->data[0] != 'l')) {
1803  ret = -1;
1804  goto end;
1805  }
1806  if (g->data[0] == 'l') {
1807  break;
1808  }
1809  }
1810 
1811  ret = 0;
1812 end:
1813  gdbr_lock_leave(g);
1814  if (ret != 0) {
1815  if (dpid) {
1816  free(dpid);
1817  }
1818  // We can't use rz_debug_pid_free here
1819  if (list) {
1820  rz_list_foreach (list, iter, dpid) {
1821  if (dpid->path) {
1822  free(dpid->path);
1823  }
1824  free(dpid);
1825  }
1826  rz_list_free(list);
1827  }
1828  return NULL;
1829  }
1830  return list;
1831 }
1832 
1834  int ret = -1;
1835  RzList *list = NULL;
1836  int tpid = -1, ttid = -1;
1837  char *ptr, *ptr2, *exec_file;
1838  RzDebugPid *dpid = NULL;
1839  RzListIter *iter = NULL;
1840 
1841  if (!g) {
1842  return NULL;
1843  }
1844 
1845  if (!gdbr_lock_enter(g)) {
1846  goto end;
1847  }
1848  if (!g->stub_features.qXfer_exec_file_read || !(exec_file = gdbr_exec_file_read(g, pid))) {
1849  exec_file = "";
1850  }
1851  if (g->stub_features.qXfer_threads_read) {
1852  // XML thread description is supported
1853  // TODO: Handle this case
1854  }
1855  if (send_msg(g, "qfThreadInfo") < 0 || read_packet(g, false) < 0 || send_ack(g) < 0 || g->data_len == 0 || g->data[0] != 'm') {
1856  ret = -1;
1857  goto end;
1858  }
1859  if (!(list = rz_list_new())) {
1860  ret = -1;
1861  goto end;
1862  }
1863  while (1) {
1864  g->data[g->data_len] = '\0';
1865  ptr = g->data + 1;
1866  while (ptr) {
1867  if ((ptr2 = strchr(ptr, ','))) {
1868  *ptr2 = '\0';
1869  ptr2++;
1870  }
1871  if (read_thread_id(ptr, &tpid, &ttid,
1872  g->stub_features.multiprocess) < 0) {
1873  ptr = ptr2;
1874  continue;
1875  }
1876  if (g->stub_features.multiprocess && tpid != pid) {
1877  ptr = ptr2;
1878  continue;
1879  }
1880  if (!(dpid = RZ_NEW0(RzDebugPid)) || !(dpid->path = strdup(exec_file))) {
1881  ret = -1;
1882  goto end;
1883  }
1884  dpid->uid = dpid->gid = -1; // TODO
1885  dpid->pid = ttid;
1886  dpid->runnable = true;
1887  // This is what linux native does as fallback, but
1888  // probably not correct.
1889  // TODO: Implement getting correct thread status from GDB
1890  dpid->status = RZ_DBG_PROC_STOP;
1891  rz_list_append(list, dpid);
1892  ptr = ptr2;
1893  }
1894  if (send_msg(g, "qsThreadInfo") < 0 || read_packet(g, false) < 0 || send_ack(g) < 0 || g->data_len == 0 || (g->data[0] != 'm' && g->data[0] != 'l')) {
1895  ret = -1;
1896  goto end;
1897  }
1898  if (g->data[0] == 'l') {
1899  break;
1900  }
1901  }
1902  // This is the all I've been able to extract from gdb so far
1903  rz_list_foreach (list, iter, dpid) {
1904  if (gdbr_is_thread_dead(g, pid, dpid->pid)) {
1905  dpid->status = RZ_DBG_PROC_DEAD;
1906  }
1907  }
1908 
1909  ret = 0;
1910 end:
1911  gdbr_lock_leave(g);
1912  if (ret != 0) {
1913  if (dpid) {
1914  free(dpid);
1915  }
1916  // We can't use rz_debug_pid_free here
1917  if (list) {
1918  rz_list_foreach (list, iter, dpid) {
1919  if (dpid->path) {
1920  free(dpid->path);
1921  }
1922  free(dpid);
1923  }
1924  rz_list_free(list);
1925  }
1926  return NULL;
1927  }
1928  return list;
1929 }
1930 
1932  ut64 off, min = UINT64_MAX;
1933  char *ptr;
1934  if (!g) {
1935  return UINT64_MAX;
1936  }
1937 
1938  if (!gdbr_lock_enter(g)) {
1939  goto end;
1940  }
1941  if (send_msg(g, "qOffsets") < 0 || read_packet(g, false) < 0 || send_ack(g) < 0 || g->data_len == 0) {
1942  min = UINT64_MAX;
1943  goto end;
1944  }
1945  if (rz_str_startswith(g->data, "TextSeg=")) {
1946  ptr = g->data + strlen("TextSeg=");
1947  if (!isxdigit(*ptr)) {
1948  goto end;
1949  }
1950  off = strtoull(ptr, NULL, 16);
1951  if (off < min) {
1952  min = off;
1953  }
1954  if (!(ptr = strchr(ptr, ';'))) {
1955  goto end;
1956  }
1957  ptr++;
1958  if (*ptr && rz_str_startswith(ptr, "DataSeg=")) {
1959  ptr += strlen("DataSeg=");
1960  if (!isxdigit(*ptr)) {
1961  goto end;
1962  }
1963  off = strtoull(ptr, NULL, 16);
1964  if (off < min) {
1965  min = off;
1966  }
1967  }
1968  goto end;
1969  }
1970  if (!rz_str_startswith(g->data, "Text=")) {
1971  goto end;
1972  }
1973  ptr = g->data + strlen("Text=");
1974  if (!isxdigit(*ptr)) {
1975  goto end;
1976  }
1977  off = strtoull(ptr, NULL, 16);
1978  if (off < min) {
1979  min = off;
1980  }
1981  if (!(ptr = strchr(ptr, ';')) || !rz_str_startswith(ptr + 1, "Data=")) {
1982  min = UINT64_MAX;
1983  goto end;
1984  }
1985  ptr += strlen(";Data=");
1986  if (!isxdigit(*ptr)) {
1987  min = UINT64_MAX;
1988  goto end;
1989  }
1990  off = strtoull(ptr, NULL, 16);
1991  if (off < min) {
1992  min = off;
1993  }
1994  if (!(ptr = strchr(ptr, ';'))) {
1995  goto end;
1996  }
1997  ptr++;
1998  if (rz_str_startswith(ptr, "Bss=")) {
1999  ptr += strlen("Bss=");
2000  if (!isxdigit(*ptr)) {
2001  goto end;
2002  }
2003  off = strtoull(ptr, NULL, 16);
2004  if (off < min) {
2005  min = off;
2006  }
2007  }
2008 end:
2009  gdbr_lock_leave(g);
2010  return min;
2011 }
size_t len
Definition: 6502dis.c:15
static char * regs[]
Definition: analysis_sh.c:203
lzma_index ** i
Definition: index.h:629
static int buf_len
Definition: asm_arc.c:22
static int value
Definition: cmd_api.c:93
RZ_API void * rz_cons_sleep_begin(void)
Definition: cons.c:443
RZ_API void rz_cons_break_pop(void)
Definition: cons.c:361
RZ_API void rz_cons_break_push(RzConsBreak cb, void *user)
Definition: cons.c:357
RZ_API void rz_cons_sleep_end(void *user)
Definition: cons.c:450
#define NULL
Definition: cris-opc.c:27
static static fork const void static count static fd const char const char static newpath const char static path const char path
Definition: sflib.h:35
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
struct @667 g
RZ_API char * sdb_fmt(const char *fmt,...)
Definition: fmt.c:26
int send_ack(libgdbr_t *g)
Functions sends a single ack ('+')
Definition: common.c:130
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
int read_packet(libgdbr_t *instance, bool vcont)
Definition: packet.c:143
int send_msg(libgdbr_t *g, const char *command)
Definition: common.c:146
const char * filename
Definition: ioapi.h:137
voidpf uLong offset
Definition: ioapi.h:144
const char int mode
Definition: ioapi.h:137
voidpf void * buf
Definition: ioapi.h:138
snprintf
Definition: kernel.h:364
#define reg(n)
uint8_t ut8
Definition: lh5801.h:11
return memset(p, 0, total)
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
#define GDB_MAX_PKTSZ
Definition: libgdbr.h:21
#define GDB_REMOTE_TYPE_LLDB
Definition: libgdbr.h:20
#define MSG_NOT_SUPPORTED
Definition: libgdbr.h:16
static void list(RzEgg *egg)
Definition: rz-gg.c:52
RZ_API RZ_OWN RzList * rz_list_new(void)
Returns a new initialized RzList pointer (free method is not initialized)
Definition: list.c:235
RZ_API RZ_BORROW RzListIter * rz_list_append(RZ_NONNULL RzList *list, void *data)
Appends at the end of the list a new element.
Definition: list.c:288
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
void * malloc(size_t size)
Definition: malloc.c:123
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
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
assert(limit<=UINT32_MAX/2)
int x
Definition: mipsasm.c:20
int type
Definition: mipsasm.c:17
int off
Definition: pal.c:13
static const char hex[16]
Definition: print.c:21
static const char * conditions[]
#define min(a, b)
Definition: qsort.h:83
int handle_G(libgdbr_t *g)
Definition: responses.c:19
int handle_M(libgdbr_t *g)
Definition: responses.c:23
int handle_lldb_read_reg(libgdbr_t *g)
Definition: responses.c:387
int handle_vFile_pread(libgdbr_t *g, ut8 *buf)
Definition: responses.c:145
int handle_m(libgdbr_t *g)
Definition: responses.c:36
int handle_vFile_close(libgdbr_t *g)
Definition: responses.c:177
int handle_setbp(libgdbr_t *g)
Definition: responses.c:116
int handle_cont(libgdbr_t *g)
Definition: responses.c:383
int handle_stop_reason(libgdbr_t *g)
Definition: responses.c:244
int handle_g(libgdbr_t *g)
Definition: responses.c:11
int handle_removebp(libgdbr_t *g)
Definition: responses.c:120
int handle_attach(libgdbr_t *g)
Definition: responses.c:124
int handle_qSupported(libgdbr_t *g)
Definition: common.c:12
int handle_vFile_open(libgdbr_t *g)
Definition: responses.c:132
int handle_qC(libgdbr_t *g)
Definition: responses.c:77
int handle_P(libgdbr_t *g)
Definition: responses.c:27
#define eprintf(x, y...)
Definition: rlcc.c:7
@ RZ_DBG_PROC_STOP
Definition: rz_debug.h:60
@ RZ_DBG_PROC_DEAD
Definition: rz_debug.h:64
RZ_API int rz_socket_close(RzSocket *s)
Definition: socket.c:419
RZ_API bool rz_socket_is_connected(RzSocket *)
Definition: socket.c:101
RZ_API int rz_socket_connect_serial(RzSocket *sock, const char *path, int speed, int parity)
Definition: socket_serial.c:63
#define rz_socket_connect_tcp(a, b, c, d)
Definition: rz_socket.h:99
RZ_API int rz_socket_write(RzSocket *s, void *buf, int len)
Definition: socket.c:724
RZ_API char * rz_str_append(char *ptr, const char *string)
Definition: str.c:1063
RZ_API bool rz_str_startswith(RZ_NONNULL const char *str, RZ_NONNULL const char *needle)
Checks if a string starts with a specifc sequence of characters (case sensitive)
Definition: str.c:3286
RZ_API char * rz_sys_getenv(const char *key)
Get the value of an environment variable named key or NULL if none exists.
Definition: sys.c:483
#define PFMT64d
Definition: rz_types.h:394
#define RZ_NEW0(x)
Definition: rz_types.h:284
int(* PrintfCallback)(const char *str,...) RZ_PRINTF_CHECK(1
Definition: rz_types.h:233
#define RZ_FREE(x)
Definition: rz_types.h:369
#define PFMT64x
Definition: rz_types.h:393
#define RZ_MIN(x, y)
#define RZ_MAX(x, y)
#define CMD_RHWA
Definition: core.h:39
#define CMD_BP
Definition: core.h:30
#define CMD_READMEM
Definition: core.h:28
#define CMD_RBP
Definition: core.h:31
#define CMD_C_CONT_SIG
Definition: core.h:43
Breakpoint
Definition: core.h:46
@ WRITE_WATCHPOINT
Definition: core.h:49
@ READ_WATCHPOINT
Definition: core.h:50
@ ACCESS_WATCHPOINT
Definition: core.h:51
@ BREAKPOINT
Definition: core.h:47
@ HARDWARE_BREAKPOINT
Definition: core.h:48
#define CMD_HWR
Definition: core.h:36
#define CMD_HBP
Definition: core.h:32
#define CMD_WRITEMEM
Definition: core.h:27
#define CMD_DETACH_MP
Definition: core.h:20
#define CMD_RHBP
Definition: core.h:33
#define CMD_HWW
Definition: core.h:34
#define CMD_ATTACH
Definition: core.h:19
#define CMD_C_STEP
Definition: core.h:44
#define CMD_RHWR
Definition: core.h:37
#define CMD_RHWW
Definition: core.h:35
#define CMD_WRITEREGS
Definition: core.h:24
#define CMD_C
Definition: core.h:41
#define CMD_C_CONT
Definition: core.h:42
#define CMD_WRITEREG
Definition: core.h:26
#define CMD_READREGS
Definition: core.h:23
#define CMD_HWA
Definition: core.h:38
#define CMD_KILL_MP
Definition: core.h:21
#define isxdigit(c)
Definition: safe-ctype.h:145
static struct sockaddr static addrlen static backlog const void static flags void flags
Definition: sfsocketcall.h:123
static int
Definition: sfsocketcall.h:114
static struct sockaddr static addrlen static backlog const void msg
Definition: sfsocketcall.h:119
#define CS8
Definition: sftypes.h:942
#define CLOCAL
Definition: sftypes.h:948
#define IGNBRK
Definition: sftypes.h:870
#define PARODD
Definition: sftypes.h:946
#define VMIN
Definition: sftypes.h:857
#define CSTOPB
Definition: sftypes.h:943
#define CRTSCTS
Definition: sftypes.h:967
#define VTIME
Definition: sftypes.h:856
#define IXON
Definition: sftypes.h:880
#define TCSANOW
Definition: sftypes.h:998
#define CREAD
Definition: sftypes.h:944
unsigned long uint64_t
Definition: sftypes.h:28
unsigned char uint8_t
Definition: sftypes.h:31
#define PARENB
Definition: sftypes.h:945
#define IXANY
Definition: sftypes.h:881
#define CSIZE
Definition: sftypes.h:938
#define IXOFF
Definition: sftypes.h:882
#define INT32_MAX
#define UINT64_MAX
Definition: z80asm.h:102
char * path
Definition: rz_debug.h:414
const char * command
Definition: main.c:7
char * message
Definition: main.c:12
uv_tty_t tty
Definition: main.c:7
int unpack_hex(const char *src, ut64 len, char *dst)
Definition: utils.c:95
int write_thread_id(char *dest, int len, int pid, int tid, bool multiprocess)
Definition: utils.c:144
int read_thread_id(const char *src, int *pid, int *tid, bool multiprocess)
Definition: utils.c:161
int pack_hex(const char *src, ut64 len, char *dst)
Definition: utils.c:111
int gdbr_write_register(libgdbr_t *g, int index, char *value, int len)
Definition: core.c:1018
int gdbr_disconnect(libgdbr_t *g)
disconnects the lib
Definition: core.c:283
int gdbr_read_memory(libgdbr_t *g, ut64 address, ut8 *buf, int len)
Definition: core.c:812
int gdbr_check_extended_mode(libgdbr_t *g)
checks for extended mode availability
Definition: core.c:406
int gdbr_remove_hwa(libgdbr_t *g, ut64 address, int sizebp)
Definition: core.c:1392
int gdbr_remove_bp(libgdbr_t *g, ut64 address, int sizebp)
Definition: core.c:1377
ut8 * buf
Definition: core.c:75
int gdbr_open_file(libgdbr_t *g, const char *filename, int flags, int mode)
Definition: core.c:1445
bool valid
Definition: core.c:77
static int gdbr_connect_lldb(libgdbr_t *g)
Definition: core.c:129
static void gdbr_break_process(void *arg)
Definition: core.c:90
int gdbr_write_registers(libgdbr_t *g, char *registers)
Definition: core.c:1096
int gdbr_check_vcont(libgdbr_t *g)
checks which subcommands of the vCont packet are supported
Definition: core.c:335
int gdbr_attach(libgdbr_t *g, int pid)
attaches to a process
Definition: core.c:439
int gdbr_remove_hwbp(libgdbr_t *g, ut64 address, int sizebp)
Definition: core.c:1380
bool gdbr_lock_tryenter(libgdbr_t *g)
Definition: core.c:96
int gdbr_read_registers(libgdbr_t *g)
Definition: core.c:685
int gdbr_connect(libgdbr_t *g, const char *host, int port)
Function connects to a gdbserver instance.
Definition: core.c:155
bool init
Definition: core.c:77
int gdbr_remove_hwr(libgdbr_t *g, ut64 address, int sizebp)
Definition: core.c:1388
ut64 maxlen
Definition: core.c:76
int gdbr_detach(libgdbr_t *g)
detaches from a process
Definition: core.c:495
bool gdbr_lock_enter(libgdbr_t *g)
Acquires the gdbr lock and sets up breaking.
Definition: core.c:105
RzList * gdbr_threads_list(libgdbr_t *g, int pid)
get list of threads for given pid
Definition: core.c:1833
int remove_bp(libgdbr_t *g, ut64 address, enum Breakpoint type, int sizebp)
Definition: core.c:1396
int gdbr_set_bp(libgdbr_t *g, ut64 address, const char *conditions, int sizebp)
Function sets normal breakpoint (0xcc, int3)
Definition: core.c:1357
char hex2char(char *hex)
Definition: utils.c:88
char * gdbr_exec_file_read(libgdbr_t *g, int pid)
Definition: core.c:1635
ut64 buflen
Definition: core.c:76
int gdbr_remove_hww(libgdbr_t *g, ut64 address, int sizebp)
Definition: core.c:1384
void gdbr_lock_leave(libgdbr_t *g)
Releases the gdbr lock.
Definition: core.c:117
RzList * gdbr_pids_list(libgdbr_t *g, int pid)
get a list of the child processes of the given pid
Definition: core.c:1731
static void reg_cache_init(libgdbr_t *g)
Definition: core.c:80
int gdbr_detach_pid(libgdbr_t *g, int pid)
Definition: core.c:520
bool gdbr_is_thread_dead(libgdbr_t *g, int pid, int tid)
Definition: core.c:1696
int gdbr_set_hwa(libgdbr_t *g, ut64 address, const char *conditions, int sizebp)
Definition: core.c:1373
int test_command(libgdbr_t *g, const char *command)
Definition: core.c:1193
static int gdbr_read_memory_page(libgdbr_t *g, ut64 address, ut8 *buf, int len)
Definition: core.c:727
int gdbr_set_hwbp(libgdbr_t *g, ut64 address, const char *conditions, int sizebp)
Definition: core.c:1361
int gdbr_step(libgdbr_t *g, int tid)
Definition: core.c:929
int gdbr_continue(libgdbr_t *g, int pid, int tid, int sig)
Definition: core.c:950
static struct @443 reg_cache
int gdbr_set_hwr(libgdbr_t *g, ut64 address, const char *conditions, int sizebp)
Definition: core.c:1369
int gdbr_write_reg(libgdbr_t *g, const char *name, char *value, int len)
Definition: core.c:1058
int gdbr_write_memory(libgdbr_t *g, ut64 address, const uint8_t *data, ut64 len)
Definition: core.c:860
int gdbr_read_file(libgdbr_t *g, ut8 *buf, ut64 max_len)
Definition: core.c:1485
ut64 gdbr_get_baddr(libgdbr_t *g)
Definition: core.c:1931
int set_bp(libgdbr_t *g, ut64 address, const char *conditions, enum Breakpoint type, int sizebp)
Definition: core.c:1302
#define QSUPPORTED_MAX_RETRIES
Definition: core.c:29
void gdbr_invalidate_reg_cache()
invalidates the reg cache
Definition: core.c:1570
int gdbr_select(libgdbr_t *g, int pid, int tid)
Definition: core.c:304
static int gdbr_read_registers_lldb(libgdbr_t *g)
Definition: core.c:653
int send_vcont(libgdbr_t *g, const char *command, const char *thread_id)
Function sends a vCont command to the gdbserver.
Definition: core.c:1212
int gdbr_kill(libgdbr_t *g)
kills the process the remote gdbserver is debugging (TODO: handle pid)
Definition: core.c:572
int gdbr_send_qRcmd(libgdbr_t *g, const char *cmd, PrintfCallback cb_printf)
sends a qRcmd packet which basically passes a command to the remote target's interpreter.
Definition: core.c:1574
int gdbr_set_hww(libgdbr_t *g, ut64 address, const char *conditions, int sizebp)
Definition: core.c:1365
int gdbr_stop_reason(libgdbr_t *g)
gets reason why remote target stopped
Definition: core.c:391
int gdbr_write_bin_registers(libgdbr_t *g, const char *regs, int len)
Function writes general purpose registers.
Definition: core.c:975
int gdbr_close_file(libgdbr_t *g)
Definition: core.c:1539
int gdbr_kill_pid(libgdbr_t *g, int pid)
Definition: core.c:605
RZ_API void rz_th_lock_leave(RZ_NONNULL RzThreadLock *thl)
Releases a RzThreadLock structure.
Definition: thread_lock.c:75
RZ_API bool rz_th_lock_tryenter(RZ_NONNULL RzThreadLock *thl)
Tries to acquire a RzThreadLock structure.
Definition: thread_lock.c:61
RZ_API void rz_th_lock_enter(RZ_NONNULL RzThreadLock *thl)
Acquires a RzThreadLock structure.
Definition: thread_lock.c:45
static st64 delta
Definition: vmenus.c:2425
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
int gdbr_read_processes_xml(libgdbr_t *g, int pid, RzList *list)
Definition: xml.c:474
int gdbr_read_target_xml(libgdbr_t *g)
Definition: xml.c:460
static const z80_opcode fd[]
Definition: z80_tab.h:997
#define buffer_size(buffer)
static void hexdump(const zip_uint8_t *data, zip_uint16_t len)
Definition: ziptool.c:692