Rizin
unix-like reverse engineering framework and cli tools
responses.h File Reference
#include <string.h>
#include "libgdbr.h"
#include "utils.h"

Go to the source code of this file.

Functions

int handle_g (libgdbr_t *g)
 
int handle_G (libgdbr_t *g)
 
int handle_m (libgdbr_t *g)
 
int handle_M (libgdbr_t *g)
 
int handle_P (libgdbr_t *g)
 
int handle_cont (libgdbr_t *g)
 
int handle_qStatus (libgdbr_t *g)
 
int handle_qC (libgdbr_t *g)
 
int handle_execFileRead (libgdbr_t *g)
 
int handle_qSupported (libgdbr_t *g)
 
int handle_setbp (libgdbr_t *g)
 
int handle_removebp (libgdbr_t *g)
 
int handle_attach (libgdbr_t *g)
 
int handle_vFile_open (libgdbr_t *g)
 
int handle_vFile_pread (libgdbr_t *g, ut8 *buf)
 
int handle_vFile_close (libgdbr_t *g)
 
int handle_stop_reason (libgdbr_t *g)
 
int handle_lldb_read_reg (libgdbr_t *g)
 

Function Documentation

◆ handle_attach()

int handle_attach ( libgdbr_t g)

Definition at line 124 of file responses.c.

124  {
125  if (g->data_len == 3 && g->data[0] == 'E') {
126  send_ack(g);
127  return -1;
128  }
129  return send_ack(g);
130 }
struct @667 g
int send_ack(libgdbr_t *g)
Functions sends a single ack ('+')
Definition: common.c:130

References g, and send_ack().

Referenced by gdbr_attach().

◆ handle_cont()

int handle_cont ( libgdbr_t g)

Definition at line 383 of file responses.c.

383  {
384  return handle_stop_reason(g);
385 }
int handle_stop_reason(libgdbr_t *g)
Definition: responses.c:244

References g, and handle_stop_reason().

Referenced by send_vcont().

◆ handle_execFileRead()

int handle_execFileRead ( libgdbr_t g)

◆ handle_g()

int handle_g ( libgdbr_t g)

For handling responses from gdbserver See Appendix E in the gdb manual (GDB Remote Serial Protocol) Packets look following: $ starts a command/packet, the end is indicated with # and a final checksum $<command>#<checksum>

Definition at line 11 of file responses.c.

11  {
12  if (unpack_hex(g->data, g->data_len, g->data) < 0) {
13  return -1;
14  }
15  g->data_len = g->data_len / 2;
16  return send_ack(g);
17 }
int unpack_hex(const char *src, ut64 len, char *dst)
Definition: utils.c:95

References g, send_ack(), and unpack_hex().

Referenced by gdbr_read_registers().

◆ handle_G()

int handle_G ( libgdbr_t g)

Definition at line 19 of file responses.c.

19  {
20  return send_ack(g);
21 }

References g, and send_ack().

Referenced by gdbr_write_bin_registers(), and gdbr_write_registers().

◆ handle_lldb_read_reg()

int handle_lldb_read_reg ( libgdbr_t g)

Definition at line 387 of file responses.c.

387  {
388  if (send_ack(g) < 0) {
389  return -1;
390  }
391  char *ptr, *ptr2, *buf;
392  size_t regnum, tot_regs, buflen = 0;
393 
394  // Get maximum register number
395  for (regnum = 0; *g->registers[regnum].name; regnum++) {
396  if (g->registers[regnum].offset + g->registers[regnum].size > buflen) {
397  buflen = g->registers[regnum].offset + g->registers[regnum].size;
398  }
399  }
400  tot_regs = regnum;
401 
402  // We're not using the receive buffer till next packet anyway. Better use it
403  buf = g->read_buff;
404  memset(buf, 0, buflen);
405 
406  if (!(ptr = strtok(g->data, ";"))) {
407  return -1;
408  }
409  while (ptr) {
410  if (!isxdigit(*ptr)) {
411  // This is not a reg value. Skip
412  ptr = strtok(NULL, ";");
413  continue;
414  }
415  // Get register number
416  regnum = (int)strtoul(ptr, NULL, 16);
417  if (regnum >= tot_regs || !(ptr2 = strchr(ptr, ':'))) {
418  ptr = strtok(NULL, ";");
419  continue;
420  }
421  ptr2++;
422  // Write to offset
423  unpack_hex(ptr2, strlen(ptr2), buf + g->registers[regnum].offset);
424  ptr = strtok(NULL, ";");
425  continue;
426  }
427  memcpy(g->data, buf, buflen);
428  g->data_len = buflen;
429  return 0;
430 }
#define NULL
Definition: cris-opc.c:27
voidpf void * buf
Definition: ioapi.h:138
return memset(p, 0, total)
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
#define isxdigit(c)
Definition: safe-ctype.h:145
static int
Definition: sfsocketcall.h:114
ut64 buflen
Definition: core.c:76

References buflen, g, int, isxdigit, memcpy(), memset(), NULL, send_ack(), and unpack_hex().

Referenced by gdbr_read_registers_lldb().

◆ handle_m()

int handle_m ( libgdbr_t g)

Definition at line 36 of file responses.c.

36  {
37  if (g->data_len == 3 && g->data[0] == 'E') {
38  // TODO: figure out if this is a problem
39  send_ack(g);
40  return -1;
41  }
42  int len = strlen(g->data);
43  g->data_len = len / 2;
44  unpack_hex(g->data, len, g->data);
45  return send_ack(g);
46 }
size_t len
Definition: 6502dis.c:15

References g, len, send_ack(), and unpack_hex().

Referenced by gdbr_read_memory_page().

◆ handle_M()

int handle_M ( libgdbr_t g)

Definition at line 23 of file responses.c.

23  {
24  return send_ack(g);
25 }

References g, and send_ack().

Referenced by gdbr_write_memory().

◆ handle_P()

int handle_P ( libgdbr_t g)

Definition at line 27 of file responses.c.

27  {
28  if (g->data_len == 0) {
29  g->last_code = MSG_NOT_SUPPORTED;
30  } else {
31  g->last_code = MSG_OK;
32  }
33  return send_ack(g);
34 }
#define MSG_OK
Definition: libgdbr.h:15
#define MSG_NOT_SUPPORTED
Definition: libgdbr.h:16

References g, MSG_NOT_SUPPORTED, MSG_OK, and send_ack().

Referenced by gdbr_write_register().

◆ handle_qC()

int handle_qC ( libgdbr_t g)

Definition at line 77 of file responses.c.

77  {
78  // We get process and thread ID
79  if (strncmp(g->data, "QC", 2)) {
80  send_ack(g);
81  return -1;
82  }
83  g->data[g->data_len] = '\0';
84  if (read_thread_id(g->data + 2, &g->pid, &g->tid, g->stub_features.multiprocess) < 0) {
85  send_ack(g);
86  return -1;
87  }
88  return send_ack(g);
89 }
int read_thread_id(const char *src, int *pid, int *tid, bool multiprocess)
Definition: utils.c:161

References g, read_thread_id(), and send_ack().

Referenced by gdbr_connect().

◆ handle_qStatus()

int handle_qStatus ( libgdbr_t g)

Definition at line 48 of file responses.c.

48  {
49  if (!g || !g->data || !*g->data) {
50  return -1;
51  }
52  char *data = strdup(g->data);
53  char *tok = strtok(data, ";");
54  if (!tok) {
55  free(data);
56  return -1;
57  }
58  // TODO: We do not yet handle the case where a trace is already running
59  if (strncmp(tok, "T0", 2)) {
60  send_ack(g);
61  free(data);
62  return -1;
63  }
64  // Ensure that trace was never run
65  while (tok != NULL) {
66  if (!strncmp(tok, "tnotrun:0", 9)) {
67  free(data);
68  return send_ack(g);
69  }
70  tok = strtok(NULL, ";");
71  }
72  send_ack(g);
73  free(data);
74  return -1;
75 }
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
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")

References free(), g, NULL, send_ack(), and strdup().

◆ handle_qSupported()

int handle_qSupported ( libgdbr_t g)

Definition at line 12 of file common.c.

12  {
13  char *tok = NULL;
14  // Catch no data received
15  if (!*g->data) {
16  return -1;
17  }
18  // TODO handle the message correct and set all infos like packetsize, thread stuff and features
19  tok = strtok(g->data, ";");
20  while (tok) {
21  if (rz_str_startswith(tok, "PacketSize=")) {
22  // Largest packet size we support is 2048
23  g->stub_features.pkt_sz = RZ_MIN(strtoul(tok + strlen("PacketSize="), NULL, 16), 2048);
24  // Shouldn't be smaller than 64 (Erroneous 0 etc.)
25  g->stub_features.pkt_sz = RZ_MAX(g->stub_features.pkt_sz, 64);
26  } else if (rz_str_startswith(tok, "qXfer:")) {
27  if (!tok[6]) {
28  tok = strtok(NULL, ";");
29  continue;
30  }
31  char *p = tok + 6;
32  if (rz_str_startswith(p, "btrace:read")) {
33  g->stub_features.qXfer_btrace_read = (p[strlen("btrace:read")] == '+');
34  } else if (rz_str_startswith(p, "btrace-conf:read")) {
35  g->stub_features.qXfer_btrace_conf_read = (p[strlen("btrace-conf:read")] == '+');
36  } else if (rz_str_startswith(p, "spu:read")) {
37  g->stub_features.qXfer_spu_read = (p[strlen("spu:read")] == '+');
38  } else if (rz_str_startswith(p, "spu:write")) {
39  g->stub_features.qXfer_spu_write = (p[strlen("spu:write")] == '+');
40  } else if (rz_str_startswith(p, "libraries:read")) {
41  g->stub_features.qXfer_libraries_read = (p[strlen("libraries:read")] == '+');
42  } else if (rz_str_startswith(p, "libraries-svr4:read")) {
43  g->stub_features.qXfer_libraries_svr4_read = (p[strlen("libraries-svr4:read")] == '+');
44  } else if (rz_str_startswith(p, "memory-map:read")) {
45  g->stub_features.qXfer_memory_map_read = (p[strlen("memory-map:read")] == '+');
46  } else if (rz_str_startswith(p, "auxv:read")) {
47  g->stub_features.qXfer_auxv_read = (p[strlen("auxv:read")] == '+');
48  } else if (rz_str_startswith(p, "exec-file:read")) {
49  g->stub_features.qXfer_exec_file_read = (p[strlen("exec-file:read")] == '+');
50  } else if (rz_str_startswith(p, "features:read")) {
51  g->stub_features.qXfer_features_read = (p[strlen("features:read")] == '+');
52  } else if (rz_str_startswith(p, "sdata:read")) {
53  g->stub_features.qXfer_sdata_read = (p[strlen("sdata:read")] == '+');
54  } else if (rz_str_startswith(p, "siginfo:read")) {
55  g->stub_features.qXfer_siginfo_read = (p[strlen("siginfo:read")] == '+');
56  } else if (rz_str_startswith(p, "siginfo:write")) {
57  g->stub_features.qXfer_siginfo_write = (p[strlen("siginfo:write")] == '+');
58  } else if (rz_str_startswith(p, "threads:read")) {
59  g->stub_features.qXfer_threads_read = (p[strlen("threads:read")] == '+');
60  } else if (rz_str_startswith(p, "traceframe-info:read")) {
61  g->stub_features.qXfer_traceframe_info_read = (p[strlen("traceframe-info:read")] == '+');
62  } else if (rz_str_startswith(p, "uib:read")) {
63  g->stub_features.qXfer_uib_read = (p[strlen("uib:read")] == '+');
64  } else if (rz_str_startswith(p, "fdpic:read")) {
65  g->stub_features.qXfer_fdpic_read = (p[strlen("fdpic:read")] == '+');
66  } else if (rz_str_startswith(p, "osdata:read")) {
67  g->stub_features.qXfer_osdata_read = (p[strlen("osdata:read")] == '+');
68  }
69  } else if (tok[0] == 'Q') {
70  if (rz_str_startswith(tok, "Qbtrace")) {
71  if (!tok[strlen("Qbtrace")]) {
72  tok = strtok(NULL, ";");
73  continue;
74  }
75  char *p = tok + 7;
76  if (rz_str_startswith(p, ":off")) {
77  g->stub_features.Qbtrace_off = (p[4] == '+');
78  } else if (rz_str_startswith(p, ":bts")) {
79  g->stub_features.Qbtrace_bts = (p[4] == '+');
80  } else if (rz_str_startswith(p, ":pt")) {
81  g->stub_features.Qbtrace_pt = (p[3] == '+');
82  } else if (rz_str_startswith(p, "-conf:bts:size")) {
83  g->stub_features.Qbtrace_conf_bts_size = (p[strlen("-conf:bts:size")] == '+');
84  } else if (rz_str_startswith(p, ":-conf:pt:size")) {
85  g->stub_features.Qbtrace_conf_pt_size = (p[strlen("-conf:pt:size")] == '+');
86  }
87  } else if (rz_str_startswith(tok, "QNonStop")) {
88  g->stub_features.QNonStop = (tok[strlen("QNonStop")] == '+');
89  } else if (rz_str_startswith(tok, "QCatchSyscalls")) {
90  g->stub_features.QCatchSyscalls = (tok[strlen("QCatchSyscalls")] == '+');
91  } else if (rz_str_startswith(tok, "QPassSignals")) {
92  g->stub_features.QPassSignals = (tok[strlen("QPassSignals")] == '+');
93  } else if (rz_str_startswith(tok, "QStartNoAckMode")) {
94  g->stub_features.QStartNoAckMode = (tok[strlen("QStartNoAckMode")] == '+');
95  } else if (rz_str_startswith(tok, "QAgent")) {
96  g->stub_features.QAgent = (tok[strlen("QAgent")] == '+');
97  } else if (rz_str_startswith(tok, "QAllow")) {
98  g->stub_features.QAllow = (tok[strlen("QAllow")] == '+');
99  } else if (rz_str_startswith(tok, "QDisableRandomization")) {
100  g->stub_features.QDisableRandomization = (tok[strlen("QDisableRandomization")] == '+');
101  } else if (rz_str_startswith(tok, "QTBuffer:size")) {
102  g->stub_features.QTBuffer_size = (tok[strlen("QTBuffer:size")] == '+');
103  } else if (rz_str_startswith(tok, "QThreadEvents")) {
104  g->stub_features.QThreadEvents = (tok[strlen("QThreadEvents")] == '+');
105  } else if (rz_str_startswith(tok, "QThreadSuffixSupported")) {
106  g->remote_type = GDB_REMOTE_TYPE_LLDB;
107  g->stub_features.lldb.QThreadSuffixSupported = (tok[strlen("QThreadSuffixSupported")] == '+');
108  } else if (rz_str_startswith(tok, "QListThreadsInStopReply")) {
109  g->remote_type = GDB_REMOTE_TYPE_LLDB;
110  g->stub_features.lldb.QListThreadsInStopReply = (tok[strlen("QListThreadsInStopReply")] == '+');
111  }
112  } else if (rz_str_startswith(tok, "multiprocess")) {
113  g->stub_features.multiprocess = (tok[strlen("multiprocess")] == '+');
114  } else if (rz_str_startswith(tok, "qEcho")) {
115  g->remote_type = GDB_REMOTE_TYPE_LLDB;
116  g->stub_features.lldb.qEcho = (tok[strlen("qEcho")] == '+');
117  } else if (rz_str_startswith(tok, "ReverseStep")) {
118  g->stub_features.ReverseStep = (tok[strlen("ReverseStep")] == '+');
119  } else if (rz_str_startswith(tok, "ReverseContinue")) {
120  g->stub_features.ReverseContinue = (tok[strlen("ReverseContinue")] == '+');
121  }
122  // TODO
123  tok = strtok(NULL, ";");
124  }
125  return send_ack(g);
126 }
void * p
Definition: libc.cpp:67
#define GDB_REMOTE_TYPE_LLDB
Definition: libgdbr.h:20
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
#define RZ_MIN(x, y)
#define RZ_MAX(x, y)
int send_ack(libgdbr_t *g)
Functions sends a single ack ('+')
Definition: common.c:130

References g, GDB_REMOTE_TYPE_LLDB, NULL, p, RZ_MAX, RZ_MIN, rz_str_startswith(), and send_ack().

Referenced by _server_handle_qSupported(), and gdbr_connect().

◆ handle_removebp()

int handle_removebp ( libgdbr_t g)

Definition at line 120 of file responses.c.

120  {
121  return send_ack(g);
122 }

References g, and send_ack().

Referenced by remove_bp().

◆ handle_setbp()

int handle_setbp ( libgdbr_t g)

Definition at line 116 of file responses.c.

116  {
117  return send_ack(g);
118 }

References g, and send_ack().

Referenced by set_bp().

◆ handle_stop_reason()

int handle_stop_reason ( libgdbr_t g)

Definition at line 244 of file responses.c.

244  {
245  send_ack(g);
246  if (g->data_len < 3) {
247  return -1;
248  }
249  switch (g->data[0]) {
250  case 'O':
251  unpack_hex(g->data + 1, g->data_len - 1, g->data + 1);
252  // g->data[g->data_len - 1] = '\0';
253  eprintf("%s", g->data + 1);
254  if (send_ack(g) < 0) {
255  return -1;
256  }
257  memset(&g->stop_reason, 0, sizeof(libgdbr_stop_reason_t));
258  g->stop_reason.signum = -1;
259  g->stop_reason.reason = RZ_DEBUG_REASON_NONE;
260  return 0;
261  case 'W':
262  return stop_reason_exit(g);
263  case 'X':
264  return stop_reason_terminated(g);
265  }
266  if (g->data[0] != 'T') {
267  return -1;
268  }
269  char *ptr1, *ptr2;
270  g->data[g->data_len] = '\0';
271  free(g->stop_reason.exec.path);
272  memset(&g->stop_reason, 0, sizeof(libgdbr_stop_reason_t));
273  g->stop_reason.core = -1;
274  if (sscanf(g->data + 1, "%02x", &g->stop_reason.signum) != 1) {
275  return -1;
276  }
277  g->stop_reason.is_valid = true;
278  g->stop_reason.reason = RZ_DEBUG_REASON_SIGNAL;
279  for (ptr1 = strtok(g->data + 3, ";"); ptr1; ptr1 = strtok(NULL, ";")) {
280  if (rz_str_startswith(ptr1, "thread") && !g->stop_reason.thread.present) {
281  if (!(ptr2 = strchr(ptr1, ':'))) {
282  continue;
283  }
284  ptr2++;
285  if (read_thread_id(ptr2, &g->stop_reason.thread.pid,
286  &g->stop_reason.thread.tid,
287  g->stub_features.multiprocess) < 0) {
288  continue;
289  }
290  g->stop_reason.thread.present = true;
291  continue;
292  }
293  if (rz_str_startswith(ptr1, "core")) {
294  if (!(ptr2 = strchr(ptr1, ':'))) {
295  continue;
296  }
297  ptr2++;
298  if (!isxdigit(*ptr2)) {
299  continue;
300  }
301  g->stop_reason.core = (int)strtol(ptr2, NULL, 16);
302  continue;
303  }
304  if (g->stop_reason.signum == 5) {
305  if (rz_str_startswith(ptr1, "watch") || rz_str_startswith(ptr1, "rwatch") || rz_str_startswith(ptr1, "awatch")) {
306  if (!(ptr2 = strchr(ptr1, ':'))) {
307  continue;
308  }
309  ptr2++;
310  if (!isxdigit(*ptr2)) {
311  continue;
312  }
313  g->stop_reason.watchpoint.addr = strtoll(ptr2, NULL, 16);
314  g->stop_reason.watchpoint.present = true;
315  continue;
316  }
317  if (rz_str_startswith(ptr1, "exec") && !g->stop_reason.exec.present) {
318  if (!(ptr2 = strchr(ptr1, ':'))) {
319  continue;
320  }
321  ptr2++;
322  if (!(g->stop_reason.exec.path = calloc(strlen(ptr1) / 2, 1))) {
323  continue;
324  }
325  unpack_hex(ptr2, strlen(ptr2), g->stop_reason.exec.path);
326  g->stop_reason.exec.present = true;
327  continue;
328  }
329  if (rz_str_startswith(ptr1, "fork") && !g->stop_reason.fork.present) {
330  if (!(ptr2 = strchr(ptr1, ':'))) {
331  continue;
332  }
333  ptr2++;
334  if (read_thread_id(ptr2, &g->stop_reason.fork.pid,
335  &g->stop_reason.fork.tid,
336  g->stub_features.multiprocess) < 0) {
337  continue;
338  }
339  g->stop_reason.fork.present = true;
340  continue;
341  }
342  if (rz_str_startswith(ptr1, "vfork") && !g->stop_reason.vfork.present) {
343  if (!(ptr2 = strchr(ptr1, ':'))) {
344  continue;
345  }
346  ptr2++;
347  if (read_thread_id(ptr2, &g->stop_reason.vfork.pid,
348  &g->stop_reason.vfork.tid,
349  g->stub_features.multiprocess) < 0) {
350  continue;
351  }
352  g->stop_reason.vfork.present = true;
353  continue;
354  }
355  if (rz_str_startswith(ptr1, "vforkdone")) {
356  g->stop_reason.vforkdone = true;
357  continue;
358  }
359  if (rz_str_startswith(ptr1, "library")) {
360  g->stop_reason.library = true;
361  continue;
362  }
363  if (rz_str_startswith(ptr1, "swbreak")) {
364  g->stop_reason.swbreak = true;
365  continue;
366  }
367  if (rz_str_startswith(ptr1, "hwbreak")) {
368  g->stop_reason.hwbreak = true;
369  continue;
370  }
371  if (rz_str_startswith(ptr1, "create")) {
372  g->stop_reason.create = true;
373  continue;
374  }
375  }
376  }
377  if (g->stop_reason.signum == 5) {
378  g->stop_reason.reason = RZ_DEBUG_REASON_BREAKPOINT;
379  }
380  return 0;
381 }
void * calloc(size_t number, size_t size)
Definition: malloc.c:102
static int stop_reason_exit(libgdbr_t *g)
Definition: responses.c:188
static int stop_reason_terminated(libgdbr_t *g)
Definition: responses.c:215
#define eprintf(x, y...)
Definition: rlcc.c:7
@ RZ_DEBUG_REASON_BREAKPOINT
Definition: rz_debug.h:94
@ RZ_DEBUG_REASON_NONE
Definition: rz_debug.h:91
@ RZ_DEBUG_REASON_SIGNAL
Definition: rz_debug.h:92

References calloc(), eprintf, free(), g, int, isxdigit, memset(), NULL, read_thread_id(), RZ_DEBUG_REASON_BREAKPOINT, RZ_DEBUG_REASON_NONE, RZ_DEBUG_REASON_SIGNAL, rz_str_startswith(), send_ack(), stop_reason_exit(), stop_reason_terminated(), and unpack_hex().

Referenced by __system(), gdbr_stop_reason(), and handle_cont().

◆ handle_vFile_close()

int handle_vFile_close ( libgdbr_t g)

Definition at line 177 of file responses.c.

177  {
178  if (g->data_len < 2 || g->data[0] != 'F' || g->data[1] == '-' || !isxdigit(g->data[1])) {
179  send_ack(g);
180  return -1;
181  }
182  return send_ack(g);
183 }

References g, isxdigit, and send_ack().

Referenced by gdbr_close_file().

◆ handle_vFile_open()

int handle_vFile_open ( libgdbr_t g)

Definition at line 132 of file responses.c.

132  {
133  if (g->data_len < 2 || g->data[0] != 'F' || g->data[1] == '-' || !isxdigit(g->data[1])) {
134  send_ack(g);
135  return -1;
136  }
137  g->data[g->data_len] = '\0';
138  if ((g->remote_file_fd = strtol(g->data + 1, NULL, 16)) <= 0) {
139  send_ack(g);
140  return -1;
141  }
142  return send_ack(g);
143 }

References g, isxdigit, NULL, and send_ack().

Referenced by gdbr_open_file().

◆ handle_vFile_pread()

int handle_vFile_pread ( libgdbr_t g,
ut8 buf 
)

Definition at line 145 of file responses.c.

145  {
146  send_ack(g);
147  char *ptr;
148  int len;
149  if (g->data_len < 3 || g->data[0] != 'F') {
150  return -1;
151  }
152  // F-1 is an error, yes, but it probably should not be fatal, since it might
153  // mean we're reading beyond file end. So this is handled in gdbr_read_file
154  if (g->data[1] == '-') {
155  return 0;
156  }
157  if (!isxdigit(g->data[1])) {
158  return -1;
159  }
160  if (sscanf(g->data, "F%x;", &len) != 1) {
161  return -1;
162  }
163  // Again, this is probably the end of file
164  if (len == 0) {
165  return 0;
166  }
167  if (!(ptr = strchr(g->data, ';')) || ptr >= g->data + g->data_len) {
168  return -1;
169  }
170  ptr++;
171  if (len > 0) {
172  memcpy(buf, ptr, len);
173  }
174  return len;
175 }

References g, isxdigit, len, memcpy(), and send_ack().

Referenced by gdbr_read_file().