Rizin
unix-like reverse engineering framework and cli tools
debug_gdb.c File Reference
#include <rz_core.h>
#include <rz_debug.h>
#include <libgdbr.h>
#include <gdbclient/commands.h>
#include "native/bt.c"

Go to the source code of this file.

Classes

struct  RzIOGdb
 
struct  rz_debug_gdb_ctx_t
 

Macros

#define UNKNOWN   (-1)
 
#define UNSUPPORTED   0
 
#define SUPPORTED   1
 
#define GDB_FILE_OPEN_MODE   (S_IRUSR | S_IWUSR | S_IXUSR)
 

Typedefs

typedef struct rz_debug_gdb_ctx_t RzDebugGdbCtx
 

Functions

static bool rz_debug_gdb_init (RzDebug *dbg, void **user)
 
static void rz_debug_gdb_fini (RzDebug *dbg, void *user)
 
static int rz_debug_gdb_attach (RzDebug *dbg, int pid)
 
static void check_connection (RzDebug *dbg)
 
static int rz_debug_gdb_step (RzDebug *dbg)
 
static RzListrz_debug_gdb_threads (RzDebug *dbg, int pid)
 
static RzListrz_debug_gdb_pids (RzDebug *dbg, int pid)
 
static int rz_debug_gdb_reg_read (RzDebug *dbg, int type, ut8 *buf, int size)
 
static RzListrz_debug_gdb_map_get (RzDebug *dbg)
 
static RzListrz_debug_gdb_modules_get (RzDebug *dbg)
 
static int rz_debug_gdb_reg_write (RzDebug *dbg, int type, const ut8 *buf, int size)
 
static int rz_debug_gdb_continue (RzDebug *dbg, int pid, int tid, int sig)
 
static RzDebugReasonType rz_debug_gdb_wait (RzDebug *dbg, int pid)
 
static int rz_debug_gdb_detach (RzDebug *dbg, int pid)
 
static const char * rz_debug_gdb_reg_profile (RzDebug *dbg)
 
static int rz_debug_gdb_set_reg_profile (RzDebug *dbg, const char *str)
 
static int rz_debug_gdb_breakpoint (RzBreakpoint *bp, RzBreakpointItem *b, bool set)
 
static bool rz_debug_gdb_kill (RzDebug *dbg, int pid, int tid, int sig)
 
static int rz_debug_gdb_select (RzDebug *dbg, int pid, int tid)
 
static RzDebugInforz_debug_gdb_info (RzDebug *dbg, const char *arg)
 
static RzListrz_debug_gdb_frames (RzDebug *dbg, ut64 at)
 

Variables

RzDebugPlugin rz_debug_plugin_gdb
 
RZ_API RzLibStruct rizin_plugin
 

Macro Definition Documentation

◆ GDB_FILE_OPEN_MODE

#define GDB_FILE_OPEN_MODE   (S_IRUSR | S_IWUSR | S_IXUSR)

◆ SUPPORTED

#define SUPPORTED   1

Definition at line 16 of file debug_gdb.c.

◆ UNKNOWN

#define UNKNOWN   (-1)

Definition at line 14 of file debug_gdb.c.

◆ UNSUPPORTED

#define UNSUPPORTED   0

Definition at line 15 of file debug_gdb.c.

Typedef Documentation

◆ RzDebugGdbCtx

Function Documentation

◆ check_connection()

static void check_connection ( RzDebug dbg)
static

Definition at line 44 of file debug_gdb.c.

44  {
46  if (!ctx->desc) {
48  }
49 }
static int rz_debug_gdb_attach(RzDebug *dbg, int pid)
Definition: debug_gdb.c:397
RzDebug * dbg
Definition: desil.c:30
void * plugin_data
Definition: rz_debug.h:296

References dbg, rz_debug_t::plugin_data, and rz_debug_gdb_attach().

Referenced by rz_debug_gdb_continue(), rz_debug_gdb_map_get(), rz_debug_gdb_reg_profile(), rz_debug_gdb_reg_read(), rz_debug_gdb_reg_write(), rz_debug_gdb_step(), and rz_debug_gdb_wait().

◆ rz_debug_gdb_attach()

static int rz_debug_gdb_attach ( RzDebug dbg,
int  pid 
)
static

Definition at line 397 of file debug_gdb.c.

397  {
399  RzIODesc *d = dbg->iob.io->desc;
400  // TODO: the core must update the dbg.swstep config var when this var is changed
401  dbg->swstep = false;
402  // eprintf ("XWJSTEP TOFALSE\n");
403  if (d && d->plugin && d->plugin->name && d->data) {
404  if (!strcmp("gdb", d->plugin->name)) {
405  RzIOGdb *g = d->data;
406  ctx->origrziogdb = (RzIOGdb **)&d->data; // TODO bit of a hack, please improve
407  ctx->support_sw_bp = UNKNOWN;
408  ctx->support_hw_bp = UNKNOWN;
409  ctx->desc = &g->desc;
410  int arch = rz_sys_arch_id(dbg->arch);
411  int bits = dbg->analysis->bits;
413  } else {
414  eprintf("ERROR: Underlying IO descriptor is not a GDB one..\n");
415  }
416  }
417  return true;
418 }
int bits(struct state *s, int need)
Definition: blast.c:72
cs_arch arch
Definition: cstool.c:13
#define UNKNOWN
Definition: debug_gdb.c:14
struct @667 g
bool gdbr_set_architecture(libgdbr_t *g, int arch, int bits)
Function initializes the architecture of the gdbsession.
Definition: libgdbr.c:52
#define eprintf(x, y...)
Definition: rlcc.c:7
RZ_API int rz_sys_arch_id(const char *arch)
Definition: sys.c:788
#define d(i)
Definition: sha256.c:44
int swstep
Definition: rz_debug.h:261
RzAnalysis * analysis
Definition: rz_debug.h:305
char * arch
Definition: rz_debug.h:242
RzIOBind iob
Definition: rz_debug.h:293
RzIO * io
Definition: rz_io.h:232
struct rz_io_desc_t * desc
Definition: rz_io.h:60

References rz_debug_t::analysis, rz_debug_t::arch, arch, rz_analysis_t::bits, bits(), d, dbg, rz_io_t::desc, eprintf, g, gdbr_set_architecture(), rz_io_bind_t::io, rz_debug_t::iob, rz_debug_t::plugin_data, rz_sys_arch_id(), rz_debug_t::swstep, and UNKNOWN.

Referenced by check_connection().

◆ rz_debug_gdb_breakpoint()

static int rz_debug_gdb_breakpoint ( RzBreakpoint bp,
RzBreakpointItem b,
bool  set 
)
static

Definition at line 461 of file debug_gdb.c.

461  {
462  RzDebug *dbg = bp->user;
464  int ret = 0, bpsize;
465  if (!b) {
466  return false;
467  }
468  bpsize = b->size;
469  // TODO handle conditions
470  switch (b->perm) {
471  case RZ_PERM_X: {
472  if (set) {
473  ret = b->hw ? gdbr_set_hwbp(ctx->desc, b->addr, "", bpsize) : gdbr_set_bp(ctx->desc, b->addr, "", bpsize);
474  } else {
475  ret = b->hw ? gdbr_remove_hwbp(ctx->desc, b->addr, bpsize) : gdbr_remove_bp(ctx->desc, b->addr, bpsize);
476  }
477  break;
478  }
479  // TODO handle size (area of watch in upper layer and then bpsize. For the moment watches are set on exact on byte
480  case RZ_PERM_W: {
481  if (set) {
482  gdbr_set_hww(ctx->desc, b->addr, "", 1);
483  } else {
484  gdbr_remove_hww(ctx->desc, b->addr, 1);
485  }
486  break;
487  }
488  case RZ_PERM_R: {
489  if (set) {
490  gdbr_set_hwr(ctx->desc, b->addr, "", 1);
491  } else {
492  gdbr_remove_hwr(ctx->desc, b->addr, 1);
493  }
494  break;
495  }
496  case RZ_PERM_ACCESS: {
497  if (set) {
498  gdbr_set_hwa(ctx->desc, b->addr, "", 1);
499  } else {
500  gdbr_remove_hwa(ctx->desc, b->addr, 1);
501  }
502  break;
503  }
504  }
505  return !ret;
506 }
const char * desc
Definition: bin_vsf.c:19
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
int gdbr_remove_hwbp(libgdbr_t *g, ut64 address, int sizebp)
Definition: core.c:1380
int gdbr_remove_hwr(libgdbr_t *g, ut64 address, int sizebp)
Definition: core.c:1388
int gdbr_set_bp(libgdbr_t *g, ut64 address, const char *conditions, int sizebp)
Function sets normal breakpoint (0xcc, int3)
Definition: core.c:1357
int gdbr_remove_hww(libgdbr_t *g, ut64 address, int sizebp)
Definition: core.c:1384
int gdbr_set_hwa(libgdbr_t *g, ut64 address, const char *conditions, int sizebp)
Definition: core.c:1373
int gdbr_set_hwbp(libgdbr_t *g, ut64 address, const char *conditions, int sizebp)
Definition: core.c:1361
int gdbr_set_hwr(libgdbr_t *g, ut64 address, const char *conditions, int sizebp)
Definition: core.c:1369
int gdbr_set_hww(libgdbr_t *g, ut64 address, const char *conditions, int sizebp)
Definition: core.c:1365
#define RZ_PERM_R
Definition: rz_types.h:93
#define RZ_PERM_ACCESS
Definition: rz_types.h:102
#define RZ_PERM_W
Definition: rz_types.h:94
#define RZ_PERM_X
Definition: rz_types.h:95
#define b(i)
Definition: sha256.c:42
void * user
Definition: rz_bp.h:79
static int addr
Definition: z80asm.c:58

References b, dbg, gdbr_remove_bp(), gdbr_remove_hwa(), gdbr_remove_hwbp(), gdbr_remove_hwr(), gdbr_remove_hww(), gdbr_set_bp(), gdbr_set_hwa(), gdbr_set_hwbp(), gdbr_set_hwr(), gdbr_set_hww(), rz_debug_t::plugin_data, RZ_PERM_ACCESS, RZ_PERM_R, RZ_PERM_W, RZ_PERM_X, and rz_bp_t::user.

◆ rz_debug_gdb_continue()

static int rz_debug_gdb_continue ( RzDebug dbg,
int  pid,
int  tid,
int  sig 
)
static

Definition at line 355 of file debug_gdb.c.

355  {
358  if (!ctx->desc) {
360  }
361  gdbr_continue(ctx->desc, pid, -1, sig); // Continue all threads
362  if (ctx->desc->stop_reason.is_valid && ctx->desc->stop_reason.thread.present) {
363  // if (desc->tid != desc->stop_reason.thread.tid) {
364  // eprintf ("thread id (%d) in reason differs from current thread id (%d)\n", dbg->pid, dbg->tid);
365  // }
366  ctx->desc->tid = ctx->desc->stop_reason.thread.tid;
367  }
368  return ctx->desc->tid;
369 }
int gdbr_continue(libgdbr_t *g, int pid, int tid, int sig)
Definition: core.c:950
static void check_connection(RzDebug *dbg)
Definition: debug_gdb.c:44
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
@ RZ_DEBUG_REASON_UNKNOWN
Definition: rz_debug.h:103

References check_connection(), dbg, gdbr_continue(), pid, rz_debug_t::plugin_data, and RZ_DEBUG_REASON_UNKNOWN.

◆ rz_debug_gdb_detach()

static int rz_debug_gdb_detach ( RzDebug dbg,
int  pid 
)
static

Definition at line 420 of file debug_gdb.c.

420  {
422  int ret = 0;
423 
424  if (pid <= 0 || !ctx->desc->stub_features.multiprocess) {
425  gdbr_detach(ctx->desc);
426  }
427  ret = gdbr_detach_pid(ctx->desc, pid);
428 
429  if (dbg->pid == pid) {
430  ctx->desc = NULL;
431  }
432  return ret;
433 }
int gdbr_detach(libgdbr_t *g)
detaches from a process
Definition: core.c:495
int gdbr_detach_pid(libgdbr_t *g, int pid)
Definition: core.c:520
#define NULL
Definition: cris-opc.c:27

References dbg, desc, gdbr_detach(), gdbr_detach_pid(), NULL, rz_debug_t::pid, pid, and rz_debug_t::plugin_data.

◆ rz_debug_gdb_fini()

static void rz_debug_gdb_fini ( RzDebug dbg,
void *  user 
)
static

Definition at line 38 of file debug_gdb.c.

38  {
39  RzDebugGdbCtx *ctx = user;
40  free(ctx);
41 }
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130

References free().

◆ rz_debug_gdb_frames()

static RzList* rz_debug_gdb_frames ( RzDebug dbg,
ut64  at 
)
static

Definition at line 570 of file debug_gdb.c.

570  {
571  return rz_debug_native_frames(dbg, at);
572 }
static RzList * rz_debug_native_frames(RzDebug *dbg, ut64 at)
Definition: bt.c:46

References dbg, and rz_debug_native_frames().

◆ rz_debug_gdb_info()

static RzDebugInfo* rz_debug_gdb_info ( RzDebug dbg,
const char *  arg 
)
static

Definition at line 529 of file debug_gdb.c.

529  {
531  RzDebugInfo *rdi;
532  if (!(rdi = RZ_NEW0(RzDebugInfo))) {
533  return NULL;
534  }
535  RzList *th_list;
536  bool list_alloc = false;
537  if (dbg->threads) {
538  th_list = dbg->threads;
539  } else {
540  th_list = rz_debug_gdb_threads(dbg, dbg->pid);
541  list_alloc = true;
542  }
543  RzDebugPid *th;
544  RzListIter *it;
545  bool found = false;
546  rz_list_foreach (th_list, it, th) {
547  if (th->pid == dbg->pid) {
548  found = true;
549  break;
550  }
551  }
552  rdi->pid = dbg->pid;
553  rdi->tid = dbg->tid;
554  rdi->exe = gdbr_exec_file_read(ctx->desc, dbg->pid);
555  rdi->status = found ? th->status : RZ_DBG_PROC_STOP;
556  rdi->uid = found ? th->uid : -1;
557  rdi->gid = found ? th->gid : -1;
558  if (gdbr_stop_reason(ctx->desc) >= 0) {
559  eprintf("signal: %d\n", ctx->desc->stop_reason.signum);
560  rdi->signum = ctx->desc->stop_reason.signum;
561  }
562  if (list_alloc) {
563  rz_list_free(th_list);
564  }
565  return rdi;
566 }
char * gdbr_exec_file_read(libgdbr_t *g, int pid)
Definition: core.c:1635
int gdbr_stop_reason(libgdbr_t *g)
gets reason why remote target stopped
Definition: core.c:391
static RzList * rz_debug_gdb_threads(RzDebug *dbg, int pid)
Definition: debug_gdb.c:61
RZ_API const KEY_TYPE bool * found
Definition: ht_inc.h:130
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
@ RZ_DBG_PROC_STOP
Definition: rz_debug.h:60
#define RZ_NEW0(x)
Definition: rz_types.h:284
RzList * threads
Definition: rz_debug.h:251

References dbg, eprintf, found, gdbr_exec_file_read(), gdbr_stop_reason(), rz_debug_pid_t::gid, NULL, rz_debug_t::pid, rz_debug_pid_t::pid, rz_debug_t::plugin_data, rdi, RZ_DBG_PROC_STOP, rz_debug_gdb_threads(), rz_list_free(), RZ_NEW0, rz_debug_pid_t::status, rz_debug_t::threads, rz_debug_t::tid, and rz_debug_pid_t::uid.

◆ rz_debug_gdb_init()

static bool rz_debug_gdb_init ( RzDebug dbg,
void **  user 
)
static

Definition at line 27 of file debug_gdb.c.

27  {
29  if (!ctx) {
30  return false;
31  }
32  ctx->support_sw_bp = UNKNOWN;
33  ctx->support_hw_bp = UNKNOWN;
34  *user = ctx;
35  return true;
36 }

References RZ_NEW0, and UNKNOWN.

◆ rz_debug_gdb_kill()

static bool rz_debug_gdb_kill ( RzDebug dbg,
int  pid,
int  tid,
int  sig 
)
static

Definition at line 508 of file debug_gdb.c.

508  {
510  // TODO kill based on pid and signal
511  if (sig != 0) {
512  if (gdbr_kill(ctx->desc) < 0) {
513  return false;
514  }
515  }
516  return true;
517 }
int gdbr_kill(libgdbr_t *g)
kills the process the remote gdbserver is debugging (TODO: handle pid)
Definition: core.c:572

References dbg, gdbr_kill(), and rz_debug_t::plugin_data.

◆ rz_debug_gdb_map_get()

static RzList* rz_debug_gdb_map_get ( RzDebug dbg)
static

Definition at line 133 of file debug_gdb.c.

133  { // TODO
136  if (!ctx->desc || ctx->desc->pid <= 0) {
137  return NULL;
138  }
139  RzList *retlist = NULL;
140  if (ctx->desc->get_baddr) {
141  ctx->desc->get_baddr = false;
142  ut64 baddr;
143  if ((baddr = gdbr_get_baddr(ctx->desc)) != UINT64_MAX) {
144  if (!(retlist = rz_list_new())) {
145  return NULL;
146  }
147  RzDebugMap *map;
148  if (!(map = rz_debug_map_new("", baddr, baddr, RZ_PERM_RX, 0))) {
149  rz_list_free(retlist);
150  return NULL;
151  }
152  rz_list_append(retlist, map);
153  return retlist;
154  }
155  }
156 
157  // Get file from GDB
158  char path[128];
159  ut8 *buf;
160  int ret;
161  // TODO don't hardcode buffer size, get from remote target
162  // (I think gdb doesn't do that, it just keeps reading till EOF)
163  // fstat info can get file size, but it doesn't work for /proc/pid/maps
164  ut64 buflen = 16384;
165  // If /proc/%d/maps is not valid for gdbserver, we return NULL, as of now
166  snprintf(path, sizeof(path) - 1, "/proc/%d/maps", ctx->desc->pid);
167 
168 #ifdef _MSC_VER
169 #define GDB_FILE_OPEN_MODE (_S_IREAD | _S_IWRITE)
170 #else
171 #define GDB_FILE_OPEN_MODE (S_IRUSR | S_IWUSR | S_IXUSR)
172 #endif
173 
174  if (gdbr_open_file(ctx->desc, path, O_RDONLY, GDB_FILE_OPEN_MODE) < 0) {
175  return NULL;
176  }
177  if (!(buf = malloc(buflen))) {
178  gdbr_close_file(ctx->desc);
179  return NULL;
180  }
181  if ((ret = gdbr_read_file(ctx->desc, buf, buflen - 1)) <= 0) {
182  gdbr_close_file(ctx->desc);
183  free(buf);
184  return NULL;
185  }
186  buf[ret] = '\0';
187 
188  // Get map list
189  int unk = 0, perm, i;
190  char *ptr, *pos_1;
191  size_t line_len;
192  char name[1024], region1[100], region2[100], perms[5];
193  RzDebugMap *map = NULL;
194  region1[0] = region2[0] = '0';
195  region1[1] = region2[1] = 'x';
196  if (!(ptr = strtok((char *)buf, "\n"))) {
197  gdbr_close_file(ctx->desc);
198  free(buf);
199  return NULL;
200  }
201  if (!(retlist = rz_list_new())) {
202  gdbr_close_file(ctx->desc);
203  free(buf);
204  return NULL;
205  }
206  while (ptr) {
207  ut64 map_start, map_end, offset;
208  bool map_is_shared = false;
209  line_len = strlen(ptr);
210  // maps files should not have empty lines
211  if (line_len == 0) {
212  break;
213  }
214  // We assume Linux target, for now, so -
215  // 7ffff7dda000-7ffff7dfd000 r-xp 00000000 08:05 265428 /usr/lib/ld-2.25.so
216  ret = sscanf(ptr, "%s %s %" PFMT64x " %*s %*s %[^\n]", &region1[2],
217  perms, &offset, name);
218  if (ret == 3) {
219  name[0] = '\0';
220  } else if (ret != 4) {
221  eprintf("%s: Unable to parse \"%s\"\nContent:\n%s\n",
222  __func__, path, buf);
223  gdbr_close_file(ctx->desc);
224  free(buf);
225  rz_list_free(retlist);
226  return NULL;
227  }
228  if (!(pos_1 = strchr(&region1[2], '-'))) {
229  ptr = strtok(NULL, "\n");
230  continue;
231  }
232  strncpy(&region2[2], pos_1 + 1, sizeof(region2) - 2 - 1);
233  if (!*name) {
234  snprintf(name, sizeof(name), "unk%d", unk++);
235  }
236  perm = 0;
237  for (i = 0; i < 5 && perms[i]; i++) {
238  switch (perms[i]) {
239  case 'r': perm |= RZ_PERM_R; break;
240  case 'w': perm |= RZ_PERM_W; break;
241  case 'x': perm |= RZ_PERM_X; break;
242  case 'p': map_is_shared = false; break;
243  case 's': map_is_shared = true; break;
244  }
245  }
246  map_start = rz_num_get(NULL, region1);
247  map_end = rz_num_get(NULL, region2);
248  if (map_start == map_end || map_end == 0) {
249  eprintf("%s: ignoring invalid map size: %s - %s\n",
250  __func__, region1, region2);
251  ptr = strtok(NULL, "\n");
252  continue;
253  }
254  if (!(map = rz_debug_map_new(name, map_start, map_end, perm, 0))) {
255  break;
256  }
257  map->offset = offset;
258  map->shared = map_is_shared;
259  map->file = strdup(name);
260  rz_list_append(retlist, map);
261  ptr = strtok(NULL, "\n");
262  }
263  gdbr_close_file(ctx->desc);
264  free(buf);
265  return retlist;
266 }
lzma_index ** i
Definition: index.h:629
static ut64 baddr(RzBinFile *bf)
Definition: bin_any.c:58
int gdbr_open_file(libgdbr_t *g, const char *filename, int flags, int mode)
Definition: core.c:1445
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 gdbr_close_file(libgdbr_t *g)
Definition: core.c:1539
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
#define GDB_FILE_OPEN_MODE
RZ_API RzDebugMap * rz_debug_map_new(char *name, ut64 addr, ut64 addr_end, int perm, int user)
Definition: dmap.c:7
size_t map(int syms, int left, int len)
Definition: enough.c:237
voidpf uLong offset
Definition: ioapi.h:144
voidpf void * buf
Definition: ioapi.h:138
snprintf
Definition: kernel.h:364
uint8_t ut8
Definition: lh5801.h:11
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
void * malloc(size_t size)
Definition: malloc.c:123
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")
RZ_API ut64 rz_num_get(RzNum *num, const char *str)
Definition: unum.c:172
#define RZ_PERM_RX
Definition: rz_types.h:97
#define PFMT64x
Definition: rz_types.h:393
#define O_RDONLY
Definition: sftypes.h:486
#define UINT64_MAX
Definition: z80asm.h:102
ut64 buflen
Definition: core.c:76
ut64(WINAPI *w32_GetEnabledXStateFeatures)()

References baddr(), buflen, check_connection(), dbg, eprintf, free(), GDB_FILE_OPEN_MODE, gdbr_close_file(), gdbr_get_baddr(), gdbr_open_file(), gdbr_read_file(), i, malloc(), map(), NULL, O_RDONLY, path, PFMT64x, rz_debug_t::plugin_data, rz_debug_map_new(), rz_list_append(), rz_list_free(), rz_list_new(), rz_num_get(), RZ_PERM_R, RZ_PERM_RX, RZ_PERM_W, RZ_PERM_X, snprintf, strdup(), UINT64_MAX, and ut64().

Referenced by rz_debug_gdb_modules_get().

◆ rz_debug_gdb_modules_get()

static RzList* rz_debug_gdb_modules_get ( RzDebug dbg)
static

Definition at line 268 of file debug_gdb.c.

268  {
269  char *lastname = NULL;
270  RzDebugMap *map;
271  RzListIter *iter, *iter2;
272  RzList *list, *last;
273  bool must_delete;
274  if (!(list = rz_debug_gdb_map_get(dbg))) {
275  return NULL;
276  }
277  if (!(last = rz_list_newf((RzListFree)rz_debug_map_free))) {
279  return NULL;
280  }
281  rz_list_foreach_safe (list, iter, iter2, map) {
282  const char *file = map->file;
283  if (!map->file) {
284  file = map->file = strdup(map->name);
285  }
286  must_delete = true;
287  if (file && *file == '/') {
288  if (!lastname || strcmp(lastname, file)) {
289  must_delete = false;
290  }
291  }
292  if (must_delete) {
294  } else {
295  rz_list_append(last, map);
296  free(lastname);
297  lastname = strdup(file);
298  }
299  }
300  list->free = NULL;
301  free(lastname);
303  return last;
304 }
static RzList * rz_debug_gdb_map_get(RzDebug *dbg)
Definition: debug_gdb.c:133
RZ_API void rz_debug_map_free(RzDebugMap *map)
Definition: dmap.c:77
static void list(RzEgg *egg)
Definition: rz-gg.c:52
RZ_API RZ_OWN RzList * rz_list_newf(RzListFree f)
Returns a new initialized RzList pointer and sets the free method.
Definition: list.c:248
RZ_API void rz_list_delete(RZ_NONNULL RzList *list, RZ_NONNULL RzListIter *iter)
Removes an entry in the list by using the RzListIter pointer.
Definition: list.c:162
void(* RzListFree)(void *ptr)
Definition: rz_list.h:11
Definition: gzappend.c:170

References dbg, free(), list(), map(), NULL, rz_debug_gdb_map_get(), rz_debug_map_free(), rz_list_append(), rz_list_delete(), rz_list_free(), rz_list_newf(), and strdup().

◆ rz_debug_gdb_pids()

static RzList* rz_debug_gdb_pids ( RzDebug dbg,
int  pid 
)
static

Definition at line 70 of file debug_gdb.c.

70  {
72  RzList *list;
73  if ((list = gdbr_pids_list(ctx->desc, pid))) {
75  }
76  return list;
77 }
RzList * gdbr_pids_list(libgdbr_t *g, int pid)
get a list of the child processes of the given pid
Definition: core.c:1731
RZ_API RzDebugPid * rz_debug_pid_free(RzDebugPid *pid)
Definition: pid.c:20

References dbg, gdbr_pids_list(), list(), pid, rz_debug_t::plugin_data, and rz_debug_pid_free().

◆ rz_debug_gdb_reg_profile()

static const char* rz_debug_gdb_reg_profile ( RzDebug dbg)
static

Definition at line 435 of file debug_gdb.c.

435  {
438  int arch = rz_sys_arch_id(dbg->arch);
439  int bits = dbg->analysis->bits;
440  // XXX This happens when rizin set dbg.backend before opening io_gdb
441  if (!ctx->desc) {
442  return gdbr_get_reg_profile(arch, bits);
443  }
444  if (!ctx->desc->target.valid) {
446  }
447  if (ctx->desc->target.regprofile) {
448  return strdup(ctx->desc->target.regprofile);
449  }
450  return NULL;
451 }
char * gdbr_get_reg_profile(int arch, int bits)
Function get gdb registers profile based on arch and bits.
Definition: libgdbr.c:76

References rz_debug_t::analysis, rz_debug_t::arch, arch, rz_analysis_t::bits, bits(), check_connection(), dbg, gdbr_get_reg_profile(), gdbr_set_architecture(), NULL, rz_debug_t::plugin_data, rz_sys_arch_id(), and strdup().

◆ rz_debug_gdb_reg_read()

static int rz_debug_gdb_reg_read ( RzDebug dbg,
int  type,
ut8 buf,
int  size 
)
static

Definition at line 79 of file debug_gdb.c.

79  {
81  int copy_size;
82  int buflen = 0;
84  if (!ctx->desc) {
86  }
87  gdbr_read_registers(ctx->desc);
88  if (!ctx->desc || !ctx->desc->data) {
89  return -1;
90  }
91  // read the len of the current area
93  if (size < ctx->desc->data_len) {
94  eprintf("rz_debug_gdb_reg_read: small buffer %d vs %d\n",
95  (int)size, (int)ctx->desc->data_len);
96  // return -1;
97  }
98  copy_size = RZ_MIN(ctx->desc->data_len, size);
99  buflen = RZ_MAX(ctx->desc->data_len, buflen);
100  if (ctx->reg_buf) {
101  // if (buf_size < copy_size) { //desc->data_len) {
102  if (buflen > ctx->buf_size) { // copy_size) {
103  ut8 *new_buf = realloc(ctx->reg_buf, buflen);
104  if (!new_buf) {
105  return -1;
106  }
107  ctx->reg_buf = new_buf;
108  ctx->buf_size = buflen;
109  }
110  } else {
111  ctx->reg_buf = calloc(buflen, 1);
112  if (!ctx->reg_buf) {
113  return -1;
114  }
115  ctx->buf_size = buflen;
116  }
117  memset((void *)(volatile void *)buf, 0, size);
118  memcpy((void *)(volatile void *)buf, ctx->desc->data, RZ_MIN(copy_size, size));
119  memset((void *)(volatile void *)ctx->reg_buf, 0, buflen);
120  memcpy((void *)(volatile void *)ctx->reg_buf, ctx->desc->data, copy_size);
121 #if 0
122  int i;
123  //for(i=0;i<168;i++) {
124  for(i=0;i<copy_size;i++) {
125  if (!(i%16)) printf ("\n0x%08x ", i);
126  printf ("%02x ", buf[i]); //(ut8)desc->data[i]);
127  }
128  printf("\n");
129 #endif
130  return ctx->desc->data_len;
131 }
RZ_API ut8 * rz_reg_get_bytes(RzReg *reg, int type, int *size)
Definition: arena.c:8
int gdbr_read_registers(libgdbr_t *g)
Definition: core.c:685
_Use_decl_annotations_ int __cdecl printf(const char *const _Format,...)
Definition: cs_driver.c:93
voidpf void uLong size
Definition: ioapi.h:138
return memset(p, 0, total)
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
void * realloc(void *ptr, size_t size)
Definition: malloc.c:144
void * calloc(size_t number, size_t size)
Definition: malloc.c:102
int type
Definition: mipsasm.c:17
#define RZ_MIN(x, y)
#define RZ_MAX(x, y)
RzReg * reg
Definition: rz_debug.h:286

References buflen, calloc(), check_connection(), dbg, desc, eprintf, free(), gdbr_read_registers(), i, memcpy(), memset(), rz_debug_t::plugin_data, printf(), realloc(), rz_debug_t::reg, RZ_DEBUG_REASON_UNKNOWN, RZ_MAX, RZ_MIN, rz_reg_get_bytes(), and type.

◆ rz_debug_gdb_reg_write()

static int rz_debug_gdb_reg_write ( RzDebug dbg,
int  type,
const ut8 buf,
int  size 
)
static

Definition at line 306 of file debug_gdb.c.

306  {
309  if (!ctx->desc) {
311  }
312  if (!ctx->reg_buf) {
313  // we cannot write registers before we once read them
314  return -1;
315  }
316  int buflen = 0;
317  int bits = dbg->analysis->bits;
318  const char *pcname = rz_reg_get_name(dbg->analysis->reg, RZ_REG_NAME_PC);
319  RzRegItem *reg = rz_reg_get(dbg->analysis->reg, pcname, 0);
320  if (reg) {
321  if (dbg->analysis->bits != reg->size) {
322  bits = reg->size;
323  }
324  }
326  // some implementations of the gdb protocol are acting weird.
327  // so winedbg is not able to write registers through the <G> packet
328  // and also it does not return the whole gdb register profile after
329  // calling <g>
330  // so this workaround resizes the small register profile buffer
331  // to the whole set and fills the rest with 0
332  if (ctx->buf_size < buflen) {
333  ut8 *new_buf = realloc(ctx->reg_buf, buflen * sizeof(ut8));
334  if (!new_buf) {
335  return -1;
336  }
337  ctx->reg_buf = new_buf;
338  memset(new_buf + ctx->buf_size, 0, buflen - ctx->buf_size);
339  }
340 
341  RzRegItem *current = NULL;
342  // We default to little endian if there's no way to get the configuration,
343  // since this was the behaviour prior to the change.
344  RzRegArena *arena = dbg->reg->regset[type].arena;
345  for (;;) {
346  current = rz_reg_next_diff(dbg->reg, type, ctx->reg_buf, buflen, current, bits);
347  if (!current) {
348  break;
349  }
350  gdbr_write_reg(ctx->desc, current->name, (char *)arena->bytes + (current->offset / 8), current->size / 8);
351  }
352  return true;
353 }
int gdbr_write_reg(libgdbr_t *g, const char *name, char *value, int len)
Definition: core.c:1058
#define reg(n)
RZ_API RzRegItem * rz_reg_get(RzReg *reg, const char *name, int type)
Definition: reg.c:344
RZ_API const char * rz_reg_get_name(RzReg *reg, int role)
Definition: reg.c:147
RZ_API RzRegItem * rz_reg_next_diff(RzReg *reg, int type, const ut8 *buf, int buflen, RzRegItem *prev_ri, int regsize)
Definition: reg.c:430
@ RZ_REG_NAME_PC
Definition: rz_reg.h:43
ut8 * bytes
Definition: rz_reg.h:131
int size
in bits> 8,16,32,64 ... 128/256
Definition: rz_reg.h:120
int offset
Offset into register profile in bits.
Definition: rz_reg.h:121
char * name
Definition: rz_reg.h:118
RzRegArena * arena
Definition: rz_reg.h:136
RzRegSet regset[RZ_REG_TYPE_LAST]
Definition: rz_reg.h:150

References rz_debug_t::analysis, rz_reg_set_t::arena, rz_analysis_t::bits, bits(), buflen, rz_reg_arena_t::bytes, check_connection(), dbg, free(), gdbr_write_reg(), memset(), rz_reg_item_t::name, NULL, rz_reg_item_t::offset, rz_debug_t::plugin_data, realloc(), reg, rz_analysis_t::reg, rz_debug_t::reg, rz_reg_t::regset, RZ_DEBUG_REASON_UNKNOWN, rz_reg_get(), rz_reg_get_bytes(), rz_reg_get_name(), RZ_REG_NAME_PC, rz_reg_next_diff(), rz_reg_item_t::size, and type.

◆ rz_debug_gdb_select()

static int rz_debug_gdb_select ( RzDebug dbg,
int  pid,
int  tid 
)
static

Definition at line 519 of file debug_gdb.c.

519  {
521  if (!ctx->desc || !*ctx->origrziogdb) {
522  ctx->desc = NULL; // TODO hacky fix, please improve. I would suggest using a **desc instead of a *desc, so it is automatically updated
523  return false;
524  }
525 
526  return gdbr_select(ctx->desc, pid, tid) >= 0;
527 }
int gdbr_select(libgdbr_t *g, int pid, int tid)
Definition: core.c:304

References dbg, gdbr_select(), NULL, pid, and rz_debug_t::plugin_data.

◆ rz_debug_gdb_set_reg_profile()

static int rz_debug_gdb_set_reg_profile ( RzDebug dbg,
const char *  str 
)
static

Definition at line 453 of file debug_gdb.c.

453  {
455  if (ctx->desc && str) {
456  return gdbr_set_reg_profile(ctx->desc, str);
457  }
458  return false;
459 }
int gdbr_set_reg_profile(libgdbr_t *g, const char *str)
Function set the gdbr internal registers profile.
Definition: libgdbr.c:125

References dbg, gdbr_set_reg_profile(), rz_debug_t::plugin_data, and cmd_descs_generate::str.

◆ rz_debug_gdb_step()

static int rz_debug_gdb_step ( RzDebug dbg)
static

Definition at line 51 of file debug_gdb.c.

51  {
54  if (!ctx->desc) {
56  }
57  gdbr_step(ctx->desc, dbg->tid);
58  return true;
59 }
int gdbr_step(libgdbr_t *g, int thread_id)
Definition: core.c:929

References check_connection(), dbg, gdbr_step(), rz_debug_t::plugin_data, RZ_DEBUG_REASON_UNKNOWN, and rz_debug_t::tid.

◆ rz_debug_gdb_threads()

static RzList* rz_debug_gdb_threads ( RzDebug dbg,
int  pid 
)
static

Definition at line 61 of file debug_gdb.c.

61  {
63  RzList *list;
64  if ((list = gdbr_threads_list(ctx->desc, pid))) {
66  }
67  return list;
68 }
RzList * gdbr_threads_list(libgdbr_t *g, int pid)
get list of threads for given pid
Definition: core.c:1833

References dbg, gdbr_threads_list(), list(), pid, rz_debug_t::plugin_data, and rz_debug_pid_free().

Referenced by rz_debug_gdb_info().

◆ rz_debug_gdb_wait()

static RzDebugReasonType rz_debug_gdb_wait ( RzDebug dbg,
int  pid 
)
static

Definition at line 371 of file debug_gdb.c.

371  {
374  if (!ctx->desc) {
376  }
377  if (!ctx->desc->stop_reason.is_valid) {
378  if (gdbr_stop_reason(ctx->desc) < 0) {
381  }
382  }
383  if (ctx->desc->stop_reason.thread.present) {
384  dbg->reason.tid = ctx->desc->stop_reason.thread.tid;
385  dbg->pid = ctx->desc->stop_reason.thread.pid;
386  dbg->tid = ctx->desc->stop_reason.thread.tid;
387  if (dbg->pid != ctx->desc->pid || dbg->tid != ctx->desc->tid) {
388  // eprintf ("= attach %d %d\n", dbg->pid, dbg->tid);
389  gdbr_select(ctx->desc, dbg->pid, dbg->tid);
390  }
391  }
392  dbg->reason.signum = ctx->desc->stop_reason.signum;
393  dbg->reason.type = ctx->desc->stop_reason.reason;
394  return ctx->desc->stop_reason.reason;
395 }
RzDebugReason reason
Definition: rz_debug.h:276

References check_connection(), dbg, gdbr_select(), gdbr_stop_reason(), rz_debug_t::pid, rz_debug_t::plugin_data, rz_debug_t::reason, RZ_DEBUG_REASON_UNKNOWN, rz_debug_reason_t::signum, rz_debug_reason_t::tid, rz_debug_t::tid, and rz_debug_reason_t::type.

Variable Documentation

◆ rizin_plugin

RZ_API RzLibStruct rizin_plugin
Initial value:
= {
.type = RZ_LIB_TYPE_DBG,
}
RzDebugPlugin rz_debug_plugin_gdb
Definition: debug_gdb.c:574
@ RZ_LIB_TYPE_DBG
Definition: rz_lib.h:70
#define RZ_VERSION
Definition: rz_version.h:8
const char * version
Definition: rz_debug.h:362

Definition at line 606 of file debug_gdb.c.

◆ rz_debug_plugin_gdb

RzDebugPlugin rz_debug_plugin_gdb
Initial value:
= {
.name = "gdb",
.license = "LGPL3",
.arch = "x86,arm,sh,mips,avr,lm32,v850,ba2",
.attach = &rz_debug_gdb_attach,
.detach = &rz_debug_gdb_detach,
.threads = &rz_debug_gdb_threads,
.canstep = 1,
.modules_get = rz_debug_gdb_modules_get,
.breakpoint = &rz_debug_gdb_breakpoint,
.reg_read = &rz_debug_gdb_reg_read,
.reg_write = &rz_debug_gdb_reg_write,
.reg_profile = (void *)rz_debug_gdb_reg_profile,
.set_reg_profile = &rz_debug_gdb_set_reg_profile,
.frames = &rz_debug_gdb_frames,
}
RzBinInfo * info(RzBinFile *bf)
Definition: bin_ne.c:86
static int rz_debug_gdb_set_reg_profile(RzDebug *dbg, const char *str)
Definition: debug_gdb.c:453
static int rz_debug_gdb_reg_read(RzDebug *dbg, int type, ut8 *buf, int size)
Definition: debug_gdb.c:79
static bool rz_debug_gdb_init(RzDebug *dbg, void **user)
Definition: debug_gdb.c:27
static int rz_debug_gdb_select(RzDebug *dbg, int pid, int tid)
Definition: debug_gdb.c:519
static int rz_debug_gdb_continue(RzDebug *dbg, int pid, int tid, int sig)
Definition: debug_gdb.c:355
static const char * rz_debug_gdb_reg_profile(RzDebug *dbg)
Definition: debug_gdb.c:435
static RzList * rz_debug_gdb_frames(RzDebug *dbg, ut64 at)
Definition: debug_gdb.c:570
static int rz_debug_gdb_step(RzDebug *dbg)
Definition: debug_gdb.c:51
static RzList * rz_debug_gdb_modules_get(RzDebug *dbg)
Definition: debug_gdb.c:268
static bool rz_debug_gdb_kill(RzDebug *dbg, int pid, int tid, int sig)
Definition: debug_gdb.c:508
static RzList * rz_debug_gdb_pids(RzDebug *dbg, int pid)
Definition: debug_gdb.c:70
static int rz_debug_gdb_breakpoint(RzBreakpoint *bp, RzBreakpointItem *b, bool set)
Definition: debug_gdb.c:461
static int rz_debug_gdb_detach(RzDebug *dbg, int pid)
Definition: debug_gdb.c:420
static int rz_debug_gdb_reg_write(RzDebug *dbg, int type, const ut8 *buf, int size)
Definition: debug_gdb.c:306
static RzDebugReasonType rz_debug_gdb_wait(RzDebug *dbg, int pid)
Definition: debug_gdb.c:371
static void rz_debug_gdb_fini(RzDebug *dbg, void *user)
Definition: debug_gdb.c:38
static RzDebugInfo * rz_debug_gdb_info(RzDebug *dbg, const char *arg)
Definition: debug_gdb.c:529
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 kill
Definition: sflib.h:64
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 static sig const char static mode static oldfd struct tms static buf static getgid static geteuid const char static filename static arg static mask struct ustat static ubuf static getppid static setsid static egid sigset_t static set struct timeval struct timezone static tz select
Definition: sflib.h:108
@ RZ_SYS_BITS_32
Definition: rz_sys.h:20
@ RZ_SYS_BITS_64
Definition: rz_sys.h:21
@ RZ_SYS_BITS_16
Definition: rz_sys.h:19

Definition at line 574 of file debug_gdb.c.