Rizin
unix-like reverse engineering framework and cli tools
linux_debug.h File Reference
#include <limits.h>
#include <sys/ptrace.h>
#include <sys/user.h>

Go to the source code of this file.

Classes

struct  user_regs_struct_x86_64
 
struct  user_regs_struct_x86_32
 

Macros

#define TRAP_BRKPT   1
 
#define TRAP_TRACE   2
 
#define TRAP_BRANCH   3
 
#define TRAP_HWBKPT   4
 
#define TRAP_UNK   5
 

Functions

bool linux_set_options (RzDebug *dbg, int pid)
 
int linux_step (RzDebug *dbg)
 
RzDebugReasonType linux_ptrace_event (RzDebug *dbg, int pid, int status, bool dowait)
 
int linux_attach (RzDebug *dbg, int pid)
 
bool linux_attach_new_process (RzDebug *dbg, int pid)
 
RzDebugInfolinux_info (RzDebug *dbg, const char *arg)
 
RzListlinux_pid_list (int pid, RzList *list)
 
RzListlinux_thread_list (RzDebug *dbg, int pid, RzList *list)
 
bool linux_select (RzDebug *dbg, int pid, int tid)
 
RzDebugPidfill_pid_info (const char *info, const char *path, int tid)
 
int linux_reg_read (RzDebug *dbg, int type, ut8 *buf, int size)
 
int linux_reg_write (RzDebug *dbg, int type, const ut8 *buf, int size)
 
RzListlinux_desc_list (int pid)
 
bool linux_stop_threads (RzDebug *dbg, int except)
 
int linux_handle_signals (RzDebug *dbg, int tid)
 
int linux_dbg_wait (RzDebug *dbg, int pid)
 
char * linux_reg_profile (RzDebug *dbg)
 
int match_pid (const void *pid_o, const void *th_o)
 

Macro Definition Documentation

◆ TRAP_BRANCH

#define TRAP_BRANCH   3

Definition at line 155 of file linux_debug.h.

◆ TRAP_BRKPT

#define TRAP_BRKPT   1

Definition at line 153 of file linux_debug.h.

◆ TRAP_HWBKPT

#define TRAP_HWBKPT   4

Definition at line 156 of file linux_debug.h.

◆ TRAP_TRACE

#define TRAP_TRACE   2

Definition at line 154 of file linux_debug.h.

◆ TRAP_UNK

#define TRAP_UNK   5

Definition at line 157 of file linux_debug.h.

Function Documentation

◆ fill_pid_info()

RzDebugPid* fill_pid_info ( const char *  info,
const char *  path,
int  tid 
)

Definition at line 789 of file linux_debug.c.

789  {
790  RzDebugPid *pid_info = RZ_NEW0(RzDebugPid);
791  if (!pid_info) {
792  return NULL;
793  }
794  char *ptr = strstr(info, "State:");
795  if (ptr) {
796  switch (*(ptr + 7)) {
797  case 'R':
798  pid_info->status = RZ_DBG_PROC_RUN;
799  break;
800  case 'S':
801  pid_info->status = RZ_DBG_PROC_SLEEP;
802  break;
803  case 'T':
804  case 't':
805  pid_info->status = RZ_DBG_PROC_STOP;
806  break;
807  case 'Z':
808  pid_info->status = RZ_DBG_PROC_ZOMBIE;
809  break;
810  case 'X':
811  pid_info->status = RZ_DBG_PROC_DEAD;
812  break;
813  default:
814  pid_info->status = RZ_DBG_PROC_SLEEP;
815  break;
816  }
817  }
818  ptr = strstr(info, "PPid:");
819  if (ptr) {
820  pid_info->ppid = atoi(ptr + 5);
821  }
822  ptr = strstr(info, "Uid:");
823  if (ptr) {
824  pid_info->uid = atoi(ptr + 5);
825  }
826  ptr = strstr(info, "Gid:");
827  if (ptr) {
828  pid_info->gid = atoi(ptr + 5);
829  }
830 
831  pid_info->pid = tid;
832  pid_info->path = path ? strdup(path) : NULL;
833  pid_info->runnable = true;
834  pid_info->pc = 0;
835  return pid_info;
836 }
RzBinInfo * info(RzBinFile *bf)
Definition: bin_ne.c:86
#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
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_DBG_PROC_RUN
Definition: rz_debug.h:61
@ RZ_DBG_PROC_STOP
Definition: rz_debug.h:60
@ RZ_DBG_PROC_ZOMBIE
Definition: rz_debug.h:63
@ RZ_DBG_PROC_DEAD
Definition: rz_debug.h:64
@ RZ_DBG_PROC_SLEEP
Definition: rz_debug.h:62
#define RZ_NEW0(x)
Definition: rz_types.h:284
char * path
Definition: rz_debug.h:414

References rz_debug_pid_t::gid, info(), NULL, rz_debug_pid_t::path, path, rz_debug_pid_t::pc, rz_debug_pid_t::pid, rz_debug_pid_t::ppid, rz_debug_pid_t::runnable, RZ_DBG_PROC_DEAD, RZ_DBG_PROC_RUN, RZ_DBG_PROC_SLEEP, RZ_DBG_PROC_STOP, RZ_DBG_PROC_ZOMBIE, RZ_NEW0, rz_debug_pid_t::status, strdup(), and rz_debug_pid_t::uid.

Referenced by linux_add_new_thread(), linux_pid_list(), and linux_thread_list().

◆ linux_attach()

int linux_attach ( RzDebug dbg,
int  pid 
)

Definition at line 718 of file linux_debug.c.

718  {
719  // First time we run: We try to attach to all "possible" threads and to the main pid
720  if (!dbg->threads) {
722  } else {
723  // This means we did a first run, so we probably attached to all possible threads already.
724  // So check if the requested thread is being traced already. If not, attach it
725  if (!rz_list_find(dbg->threads, &pid, &match_pid)) {
727  }
728  }
729  return pid;
730 }
RzDebug * dbg
Definition: desil.c:30
RZ_API RZ_BORROW RzListIter * rz_list_find(RZ_NONNULL const RzList *list, const void *p, RZ_NONNULL RzListComparator cmp)
Returns RzListIter element which matches via the RzListComparator.
Definition: list.c:620
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
int match_pid(const void *pid_o, const void *th_o)
Definition: linux_debug.c:608
static RzList * get_pid_thread_list(RzDebug *dbg, int main_pid)
Definition: linux_debug.c:709
static bool linux_attach_single_pid(RzDebug *dbg, int ptid)
Definition: linux_debug.c:676
RzList * threads
Definition: rz_debug.h:251

References dbg, get_pid_thread_list(), linux_attach_single_pid(), match_pid(), pid, rz_list_find(), and rz_debug_t::threads.

Referenced by linux_attach_new_process(), and linux_select().

◆ linux_attach_new_process()

bool linux_attach_new_process ( RzDebug dbg,
int  pid 
)

Definition at line 451 of file linux_debug.c.

451  {
453  if (dbg->threads) {
455  dbg->threads = NULL;
456  }
457 
458  if (!linux_attach(dbg, pid)) {
459  return false;
460  }
461 
462  // Call select to syncrhonize the thread's data.
463  dbg->pid = pid;
464  dbg->tid = pid;
466 
467  return true;
468 }
RZ_API bool rz_debug_select(RzDebug *dbg, int pid, int tid)
Definition: debug.c:595
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
int linux_attach(RzDebug *dbg, int pid)
Definition: linux_debug.c:718
static void linux_detach_all(RzDebug *dbg)
Definition: linux_debug.c:410

References dbg, linux_attach(), linux_detach_all(), NULL, rz_debug_t::pid, pid, rz_debug_select(), rz_list_free(), rz_debug_t::threads, and rz_debug_t::tid.

Referenced by linux_select(), and rz_debug_continue_kill().

◆ linux_dbg_wait()

int linux_dbg_wait ( RzDebug dbg,
int  pid 
)

Definition at line 502 of file linux_debug.c.

502  {
504  int tid = 0;
505  int status, flags = __WALL;
506  int ret = -1;
507 
508  if (pid == -1) {
509  flags |= WNOHANG;
510  }
511 
512  for (;;) {
513  // In the main context, SIGINT is propagated to the debuggee if it is
514  // in the same process group. Otherwise, the task is running in
515  // background and SIGINT will not be propagated to the debuggee.
516  if (rz_cons_context_is_main()) {
518  } else {
520  }
521  void *bed = rz_cons_sleep_begin();
522  if (dbg->continue_all_threads) {
523  ret = waitpid(-1, &status, flags);
524  } else {
525  ret = waitpid(pid, &status, flags);
526  }
527  rz_cons_sleep_end(bed);
529 
530  if (ret < 0) {
531  // Continue when interrupted by user;
532  if (errno == EINTR) {
533  continue;
534  }
535  perror("waitpid");
536  break;
537  } else if (ret == 0) {
538  // Unset WNOHANG to call next waitpid in blocking mode.
539  flags &= ~WNOHANG;
540  } else {
541  tid = ret;
542 
543  // Handle SIGTRAP with PTRACE_EVENT_*
544  reason = linux_ptrace_event(dbg, tid, status, true);
545  if (reason != RZ_DEBUG_REASON_UNKNOWN) {
546  break;
547  }
548 
549  if (WIFEXITED(status)) {
550  if (tid == dbg->main_pid) {
552  dbg->threads = NULL;
553  reason = RZ_DEBUG_REASON_DEAD;
554  eprintf("(%d) Process terminated with status %d\n", tid, WEXITSTATUS(status));
555  break;
556  } else {
557  eprintf("(%d) Child terminated with status %d\n", tid, WEXITSTATUS(status));
558  linux_remove_thread(dbg, tid);
559  continue;
560  }
561  } else if (WIFSIGNALED(status)) {
562  eprintf("child received signal %d\n", WTERMSIG(status));
563  reason = RZ_DEBUG_REASON_SIGNAL;
564  } else if (WIFSTOPPED(status)) {
565  // If tid is not in the thread list and stopped by SIGSTOP,
566  // handle it as a new task.
567  if (!rz_list_find(dbg->threads, &tid, &match_pid) &&
568  WSTOPSIG(status) == SIGSTOP) {
569  reason = linux_handle_new_task(dbg, tid);
570  if (reason != RZ_DEBUG_REASON_UNKNOWN) {
571  break;
572  }
573  }
574 
575  if (linux_handle_signals(dbg, tid)) {
576  reason = dbg->reason.type;
577  } else {
578  eprintf("can't handle signals\n");
579  return RZ_DEBUG_REASON_ERROR;
580  }
581 #ifdef WIFCONTINUED
582  } else if (WIFCONTINUED(status)) {
583  eprintf("child continued...\n");
584  reason = RZ_DEBUG_REASON_NONE;
585 #endif
586  } else if (status == 1) {
587  eprintf("debugger is dead with status 1\n");
588  reason = RZ_DEBUG_REASON_DEAD;
589  } else if (status == 0) {
590  eprintf("debugger is dead with status 0\n");
591  reason = RZ_DEBUG_REASON_DEAD;
592  } else {
593  if (ret != tid) {
594  reason = RZ_DEBUG_REASON_NEW_PID;
595  } else {
596  eprintf("returning from wait without knowing why...\n");
597  }
598  }
599  if (reason != RZ_DEBUG_REASON_UNKNOWN) {
600  break;
601  }
602  }
603  }
604  dbg->reason.tid = tid;
605  return reason;
606 }
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
RZ_API bool rz_cons_context_is_main(void)
Definition: cons.c:913
static const char struct stat static buf struct stat static buf static vhangup int status
Definition: sflib.h:145
int linux_handle_signals(RzDebug *dbg, int tid)
Definition: linux_debug.c:103
static void linux_dbg_wait_break(RzDebug *dbg)
Definition: linux_debug.c:496
static void linux_dbg_wait_break_main(RzDebug *dbg)
Definition: linux_debug.c:470
static RzDebugReasonType linux_handle_new_task(RzDebug *dbg, int tid)
Definition: linux_debug.c:330
static void linux_remove_thread(RzDebug *dbg, int pid)
Definition: linux_debug.c:430
RzDebugReasonType linux_ptrace_event(RzDebug *dbg, int pid, int status, bool dowait)
#define eprintf(x, y...)
Definition: rlcc.c:7
RzDebugReasonType
Definition: rz_debug.h:89
@ RZ_DEBUG_REASON_DEAD
Definition: rz_debug.h:90
@ RZ_DEBUG_REASON_UNKNOWN
Definition: rz_debug.h:103
@ RZ_DEBUG_REASON_ERROR
Definition: rz_debug.h:104
@ RZ_DEBUG_REASON_NONE
Definition: rz_debug.h:91
@ RZ_DEBUG_REASON_NEW_PID
Definition: rz_debug.h:105
@ RZ_DEBUG_REASON_SIGNAL
Definition: rz_debug.h:92
static struct sockaddr static addrlen static backlog const void static flags void flags
Definition: sfsocketcall.h:123
#define EINTR
Definition: sftypes.h:114
bool continue_all_threads
Definition: rz_debug.h:272
RzDebugReason reason
Definition: rz_debug.h:276
int main_pid
Definition: rz_debug.h:246

References rz_debug_t::continue_all_threads, dbg, EINTR, eprintf, flags, linux_dbg_wait_break(), linux_dbg_wait_break_main(), linux_handle_new_task(), linux_handle_signals(), linux_ptrace_event(), linux_remove_thread(), rz_debug_t::main_pid, match_pid(), NULL, pid, rz_debug_t::reason, rz_cons_break_pop(), rz_cons_break_push(), rz_cons_context_is_main(), rz_cons_sleep_begin(), rz_cons_sleep_end(), RZ_DEBUG_REASON_DEAD, RZ_DEBUG_REASON_ERROR, RZ_DEBUG_REASON_NEW_PID, RZ_DEBUG_REASON_NONE, RZ_DEBUG_REASON_SIGNAL, RZ_DEBUG_REASON_UNKNOWN, rz_list_find(), rz_list_free(), status, rz_debug_t::threads, rz_debug_reason_t::tid, and rz_debug_reason_t::type.

◆ linux_desc_list()

RzList* linux_desc_list ( int  pid)

Definition at line 1319 of file linux_debug.c.

1319  {
1320  RzList *ret = NULL;
1321  char path[512], file[512], buf[512];
1322  struct dirent *de;
1323  RzDebugDesc *desc;
1324  int type, perm;
1325  int len, len2;
1326  struct stat st;
1327  DIR *dd = NULL;
1328 
1329  rz_strf(path, "/proc/%i/fd/", pid);
1330  if (!(dd = opendir(path))) {
1331  rz_sys_perror("opendir /proc/x/fd");
1332  return NULL;
1333  }
1335  if (!ret) {
1336  closedir(dd);
1337  return NULL;
1338  }
1339  while ((de = (struct dirent *)readdir(dd))) {
1340  if (de->d_name[0] == '.') {
1341  continue;
1342  }
1343  len = strlen(path);
1344  len2 = strlen(de->d_name);
1345  if (len + len2 + 1 >= sizeof(file)) {
1346  RZ_LOG_ERROR("Filename is too long.\n");
1347  goto fail;
1348  }
1349  memcpy(file, path, len);
1350  memcpy(file + len, de->d_name, len2 + 1);
1351  buf[0] = 0;
1352  if (readlink(file, buf, sizeof(buf) - 1) == -1) {
1353  RZ_LOG_ERROR("readlink %s failed.\n", file);
1354  goto fail;
1355  }
1356  buf[sizeof(buf) - 1] = 0;
1357  type = perm = 0;
1358  if (stat(file, &st) != -1) {
1359  type = st.st_mode & S_IFIFO ? 'P' :
1360 #ifdef S_IFSOCK
1361  st.st_mode & S_IFSOCK ? 'S'
1362  :
1363 #endif
1364  st.st_mode & S_IFCHR ? 'C'
1365  : '-';
1366  }
1367  if (lstat(path, &st) != -1) {
1368  if (st.st_mode & S_IRUSR) {
1369  perm |= RZ_PERM_R;
1370  }
1371  if (st.st_mode & S_IWUSR) {
1372  perm |= RZ_PERM_W;
1373  }
1374  }
1375  // TODO: Offset
1376  desc = rz_debug_desc_new(atoi(de->d_name), buf, perm, type, 0);
1377  if (!desc) {
1378  break;
1379  }
1380  rz_list_append(ret, desc);
1381  }
1382  closedir(dd);
1383  return ret;
1384 
1385 fail:
1386  rz_list_free(ret);
1387  closedir(dd);
1388  return NULL;
1389 }
size_t len
Definition: 6502dis.c:15
const char * desc
Definition: bin_vsf.c:19
static static sync static getppid static getegid const char static filename char static len readlink
Definition: sflib.h:65
RZ_API RzDebugDesc * rz_debug_desc_new(int fd, char *path, int perm, int type, int off)
Definition: ddesc.c:8
RZ_API void rz_debug_desc_free(RzDebugDesc *p)
Definition: ddesc.c:20
voidpf void * buf
Definition: ioapi.h:138
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
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 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
static stat
Definition: sflib.h:131
static static fork const void static count static fd const char static mode const char static pathname const char static path const char static dev const char static group static getpid static getuid void void static data static pause const char static mode static sync const char const char static newpath const char static pathname unsigned long static filedes void static end_data_segment static handler static getegid char static len static pgid const char static path static newfd static getpgrp static euid const sigset_t static mask const char static len const gid_t static list const char const char static newpath const char static library readdir
Definition: sflib.h:120
int type
Definition: mipsasm.c:17
void(* RzListFree)(void *ptr)
Definition: rz_list.h:11
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
#define rz_strf(buf,...)
Convenience macro for local temporary strings.
Definition: rz_str.h:59
#define rz_sys_perror(x)
Definition: rz_types.h:336
#define RZ_PERM_R
Definition: rz_types.h:93
#define RZ_PERM_W
Definition: rz_types.h:94
Definition: sftypes.h:48
char d_name[256]
Definition: sftypes.h:52
Definition: gzappend.c:170
Definition: sftypes.h:80
#define fail(test)
Definition: tests.h:29
static const z80_opcode dd[]
Definition: z80_tab.h:844

References dirent::d_name, dd, desc, fail, len, memcpy(), NULL, path, pid, readdir, readlink, rz_debug_desc_free(), rz_debug_desc_new(), rz_list_append(), rz_list_free(), rz_list_newf(), RZ_LOG_ERROR, RZ_PERM_R, RZ_PERM_W, rz_strf, rz_sys_perror, stat, and type.

◆ linux_handle_signals()

int linux_handle_signals ( RzDebug dbg,
int  tid 
)

Definition at line 103 of file linux_debug.c.

103  {
104  siginfo_t siginfo = { 0 };
105  int ret = rz_debug_ptrace(dbg, PTRACE_GETSIGINFO, tid, 0, (rz_ptrace_data_t)(size_t)&siginfo);
106  if (ret == -1) {
107  /* ESRCH means the process already went away :-/ */
108  if (errno == ESRCH) {
110  return true;
111  }
112  rz_sys_perror("ptrace GETSIGINFO");
113  return false;
114  }
115 
116  if (siginfo.si_signo > 0) {
117  // siginfo_t newsiginfo = {0};
118  // ptrace (PTRACE_SETSIGINFO, dbg->pid, 0, &siginfo);
120  dbg->reason.signum = siginfo.si_signo;
121  dbg->stopaddr = (ut64)(size_t)siginfo.si_addr;
122  // dbg->errno = siginfo.si_errno;
123  // siginfo.si_code -> HWBKPT, USER, KERNEL or WHAT
124  // TODO: DO MORE RDEBUGREASON HERE
125  switch (dbg->reason.signum) {
126  case SIGTRAP: {
127  if (dbg->glob_libs || dbg->glob_unlibs) {
128  ut64 pc_addr = rz_debug_reg_get(dbg, "PC");
130  if (b && b->internal) {
131  char *p = strstr(b->data, "dbg.");
132  if (p) {
133  if (rz_str_startswith(p, "dbg.libs")) {
134  const char *name;
135  if (strstr(b->data, "sym.imp.dlopen")) {
137  } else {
139  }
140  b->data = rz_str_appendf(b->data, ";ps@r:%s", name);
142  break;
143  } else if (rz_str_startswith(p, "dbg.unlibs")) {
145  break;
146  }
147  }
148  }
149  }
152  if (siginfo.si_code == TRAP_TRACE) {
154  } else {
155  dbg->reason.bp_addr = (ut64)(size_t)siginfo.si_addr;
157  // Switch to the thread that hit the breakpoint
158  rz_debug_select(dbg, dbg->pid, tid);
159  dbg->tid = tid;
160  }
161  }
162  } break;
163  case SIGINT:
165  break;
166  case SIGABRT: // 6 / SIGIOT // SIGABRT
168  break;
169  case SIGSEGV:
171  break;
172  case SIGCHLD:
174  break;
175  default:
176  break;
177  }
178  if (dbg->reason.signum != SIGTRAP &&
179  (dbg->reason.signum != SIGINT || !rz_cons_is_breaked())) {
180  eprintf("[+] SIGNAL %d errno=%d addr=0x%08" PFMT64x
181  " code=%d si_pid=%d ret=%d\n",
182  siginfo.si_signo, siginfo.si_errno,
183  (ut64)(size_t)siginfo.si_addr, siginfo.si_code, siginfo.si_pid, ret);
184  }
185  return true;
186  }
187  return false;
188 }
RZ_API RZ_BORROW RzBreakpointItem * rz_bp_get_ending_at(RZ_NONNULL RzBreakpoint *bp, ut64 addr)
Get the breakpoint b that fulfills b->addr + b-> size == addr After hitting a (usually software) brea...
Definition: bp.c:119
RZ_API bool rz_cons_is_breaked(void)
Definition: cons.c:373
RZ_API ut64 rz_debug_reg_get(RzDebug *dbg, const char *name)
Definition: dreg.c:99
void * p
Definition: libc.cpp:67
#define TRAP_TRACE
Definition: linux_debug.h:154
const char * name
Definition: op.c:541
RZ_API const char * rz_reg_get_name(RzReg *reg, int role)
Definition: reg.c:147
@ RZ_DEBUG_REASON_STEP
Definition: rz_debug.h:98
@ RZ_DEBUG_REASON_BREAKPOINT
Definition: rz_debug.h:94
@ RZ_DEBUG_REASON_USERSUSP
Definition: rz_debug.h:115
@ RZ_DEBUG_REASON_ABORT
Definition: rz_debug.h:99
@ RZ_DEBUG_REASON_NEW_LIB
Definition: rz_debug.h:107
@ RZ_DEBUG_REASON_EXIT_LIB
Definition: rz_debug.h:110
@ RZ_DEBUG_REASON_SEGFAULT
Definition: rz_debug.h:93
@ RZ_REG_NAME_A1
Definition: rz_reg.h:50
@ RZ_REG_NAME_A0
Definition: rz_reg.h:49
RZ_API char * rz_str_appendf(char *ptr, const char *fmt,...) RZ_PRINTF_CHECK(2
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 PFMT64x
Definition: rz_types.h:393
#define ESRCH
Definition: sftypes.h:113
#define b(i)
Definition: sha256.c:42
Definition: z80asm.h:102
ut64 stopaddr
Definition: rz_debug.h:278
char * glob_unlibs
Definition: rz_debug.h:270
char * glob_libs
Definition: rz_debug.h:269
RzReg * reg
Definition: rz_debug.h:286
RzBreakpoint * bp
Definition: rz_debug.h:288
ut64(WINAPI *w32_GetEnabledXStateFeatures)()

References b, rz_debug_t::bp, rz_debug_reason_t::bp_addr, dbg, eprintf, ESRCH, rz_debug_t::glob_libs, rz_debug_t::glob_unlibs, name, p, PFMT64x, rz_debug_t::pid, rz_debug_t::reason, rz_debug_t::reg, rz_bp_get_ending_at(), rz_cons_is_breaked(), RZ_DEBUG_REASON_ABORT, RZ_DEBUG_REASON_BREAKPOINT, RZ_DEBUG_REASON_DEAD, RZ_DEBUG_REASON_EXIT_LIB, RZ_DEBUG_REASON_NEW_LIB, RZ_DEBUG_REASON_SEGFAULT, RZ_DEBUG_REASON_SIGNAL, RZ_DEBUG_REASON_STEP, RZ_DEBUG_REASON_USERSUSP, rz_debug_reg_get(), rz_debug_select(), rz_reg_get_name(), RZ_REG_NAME_A0, RZ_REG_NAME_A1, rz_str_appendf(), rz_str_startswith(), rz_sys_perror, rz_debug_reason_t::signum, rz_debug_t::stopaddr, rz_debug_t::tid, TRAP_TRACE, rz_debug_reason_t::type, and ut64().

Referenced by linux_dbg_wait().

◆ linux_info()

RzDebugInfo* linux_info ( RzDebug dbg,
const char *  arg 
)

Definition at line 745 of file linux_debug.c.

745  {
746  char proc_buff[1024];
748  if (!rdi) {
749  return NULL;
750  }
751 
752  RzList *th_list;
753  bool list_alloc = false;
754  if (dbg->threads) {
755  th_list = dbg->threads;
756  } else {
757  th_list = rz_list_new();
758  list_alloc = true;
759  if (th_list) {
760  th_list = linux_thread_list(dbg, dbg->pid, th_list);
761  }
762  }
763  RzDebugPid *th;
764  RzListIter *it;
765  bool found = false;
766  rz_list_foreach (th_list, it, th) {
767  if (th->pid == dbg->pid) {
768  found = true;
769  break;
770  }
771  }
772  rdi->pid = dbg->pid;
773  rdi->tid = dbg->tid;
774  rdi->uid = found ? th->uid : -1;
775  rdi->gid = found ? th->gid : -1;
776  rdi->cwd = read_link(rdi->pid, "cwd");
777  rdi->exe = read_link(rdi->pid, "exe");
778  snprintf(proc_buff, sizeof(proc_buff), "/proc/%d/cmdline", rdi->pid);
779  rdi->cmdline = rz_file_slurp(proc_buff, NULL);
780  snprintf(proc_buff, sizeof(proc_buff), "/proc/%d/stack", rdi->pid);
781  rdi->kernel_stack = rz_file_slurp(proc_buff, NULL);
782  rdi->status = found ? th->status : RZ_DBG_PROC_STOP;
783  if (list_alloc) {
784  rz_list_free(th_list);
785  }
786  return rdi;
787 }
RZ_API const KEY_TYPE bool * found
Definition: ht_inc.h:130
snprintf
Definition: kernel.h:364
RZ_API RZ_OWN RzList * rz_list_new(void)
Returns a new initialized RzList pointer (free method is not initialized)
Definition: list.c:235
static char * read_link(int pid, const char *file)
Definition: linux_debug.c:732
RzList * linux_thread_list(RzDebug *dbg, int pid, RzList *list)
Definition: linux_debug.c:875
RZ_API RZ_OWN char * rz_file_slurp(const char *str, RZ_NULLABLE size_t *usz)
Definition: file.c:454

References dbg, found, rz_debug_pid_t::gid, linux_thread_list(), NULL, rz_debug_t::pid, rz_debug_pid_t::pid, rdi, read_link(), RZ_DBG_PROC_STOP, rz_file_slurp(), rz_list_free(), rz_list_new(), RZ_NEW0, snprintf, rz_debug_pid_t::status, rz_debug_t::threads, rz_debug_t::tid, and rz_debug_pid_t::uid.

◆ linux_pid_list()

RzList* linux_pid_list ( int  pid,
RzList list 
)

Definition at line 838 of file linux_debug.c.

838  {
840  DIR *dh = NULL;
841  struct dirent *de = NULL;
842  char path[PATH_MAX], info[PATH_MAX];
843  int i = -1;
844  RzDebugPid *pid_info = NULL;
845  dh = opendir("/proc");
846  if (!dh) {
847  rz_sys_perror("opendir /proc");
849  return NULL;
850  }
851  while ((de = readdir(dh))) {
852  path[0] = 0;
853  info[0] = 0;
854  // For each existing pid file
855  if ((i = atoi(de->d_name)) <= 0) {
856  continue;
857  }
858 
859  procfs_pid_slurp(i, "cmdline", path, sizeof(path));
860  if (!procfs_pid_slurp(i, "status", info, sizeof(info))) {
861  // Get information about pid (status, pc, etc.)
862  pid_info = fill_pid_info(info, path, i);
863  } else {
864  pid_info = rz_debug_pid_new(path, i, 0, RZ_DBG_PROC_STOP, 0);
865  }
866  // Unless pid 0 is requested, only add the requested pid and it's child processes
867  if (0 == pid || i == pid || pid_info->ppid == pid) {
868  rz_list_append(list, pid_info);
869  }
870  }
871  closedir(dh);
872  return list;
873 }
lzma_index ** i
Definition: index.h:629
static void list(RzEgg *egg)
Definition: rz-gg.c:52
RzDebugPid * fill_pid_info(const char *info, const char *path, int tid)
Definition: linux_debug.c:789
RZ_API RzDebugPid * rz_debug_pid_free(RzDebugPid *pid)
Definition: pid.c:20
RZ_API RzDebugPid * rz_debug_pid_new(const char *path, int pid, int uid, char status, ut64 pc)
Definition: pid.c:6
int procfs_pid_slurp(int pid, char *prop, char *out, size_t len)
Definition: procfs.c:7

References dirent::d_name, fill_pid_info(), i, info(), list(), NULL, path, pid, rz_debug_pid_t::ppid, procfs_pid_slurp(), readdir, RZ_DBG_PROC_STOP, rz_debug_pid_free(), rz_debug_pid_new(), rz_list_append(), rz_list_free(), and rz_sys_perror.

◆ linux_ptrace_event()

RzDebugReasonType linux_ptrace_event ( RzDebug dbg,
int  pid,
int  status,
bool  dowait 
)

◆ linux_reg_profile()

char* linux_reg_profile ( RzDebug dbg)

Definition at line 55 of file linux_debug.c.

55  {
56 #if __arm__
57 #include "reg/linux-arm.h"
58 #elif __riscv
59 #include "reg/linux-riscv64.h"
60 #elif __arm64__ || __aarch64__
61 #include "reg/linux-arm64.h"
62 #elif __mips__
63  if ((dbg->bits & RZ_SYS_BITS_32) && (dbg->bp->endian == 1)) {
64 #include "reg/linux-mips.h"
65  } else {
66 #include "reg/linux-mips64.h"
67  }
68 #elif (__i386__ || __x86_64__)
69  if (dbg->bits & RZ_SYS_BITS_32) {
70 #if __x86_64__
71 #include "reg/linux-x64-32.h"
72 #else
73 #include "reg/linux-x86.h"
74 #endif
75  } else {
76 #include "reg/linux-x64.h"
77  }
78 #elif __powerpc__
79  if (dbg->bits & RZ_SYS_BITS_32) {
80 #include "reg/linux-ppc.h"
81  } else {
82 #include "reg/linux-ppc64.h"
83  }
84 #elif __s390x__
85 #include "reg/linux-s390x.h"
86 #else
87 #error "Unsupported Linux CPU"
88  return NULL;
89 #endif
90 }
@ RZ_SYS_BITS_32
Definition: rz_sys.h:20
int endian
Definition: rz_bp.h:82
int bits
Definition: rz_debug.h:243

References rz_debug_t::bits, rz_debug_t::bp, dbg, rz_bp_t::endian, NULL, and RZ_SYS_BITS_32.

◆ linux_reg_read()

int linux_reg_read ( RzDebug dbg,
int  type,
ut8 buf,
int  size 
)

Definition at line 1090 of file linux_debug.c.

1090  {
1091  bool showfpu = false;
1092  int pid = dbg->tid;
1093  int ret = 0;
1094  if (type < -1) {
1095  showfpu = true;
1096  type = -type;
1097  }
1098  switch (type) {
1099  case RZ_REG_TYPE_DRX:
1100 #if __POWERPC__
1101  // no drx for powerpc
1102  return false;
1103 #elif __i386__ || __x86_64__
1104 #if !__ANDROID__
1105  {
1106  int i;
1107  for (i = 0; i < 8; i++) { // DR0-DR7
1108  if (i == 4 || i == 5) {
1109  continue;
1110  }
1111  long ret = rz_debug_ptrace(dbg, PTRACE_PEEKUSER, pid,
1112  (void *)rz_offsetof(struct user, u_debugreg[i]), 0);
1113  if ((i + 1) * sizeof(ret) > size) {
1114  eprintf("linux_reg_get: Buffer too small %d\n", size);
1115  break;
1116  }
1117  memcpy(buf + (i * sizeof(ret)), &ret, sizeof(ret));
1118  }
1119  struct user a;
1120  return sizeof(a.u_debugreg);
1121  }
1122 #else
1123 #warning Android X86 does not support DRX
1124 #endif
1125 #endif
1126  return true;
1127  break;
1128  case RZ_REG_TYPE_FPU:
1129  case RZ_REG_TYPE_MMX:
1130  case RZ_REG_TYPE_XMM:
1131 #if __POWERPC__
1132  return false;
1133 #elif __x86_64__ || __i386__
1134  {
1135  struct user_fpregs_struct fpregs;
1136  if (type == RZ_REG_TYPE_FPU) {
1137 #if __x86_64__
1138  ret = rz_debug_ptrace(dbg, PTRACE_GETFPREGS, pid, NULL, &fpregs);
1139  if (ret != 0) {
1140  rz_sys_perror("PTRACE_GETFPREGS");
1141  return false;
1142  }
1143  if (showfpu) {
1144  print_fpu((void *)&fpregs);
1145  }
1146  size = RZ_MIN(sizeof(fpregs), size);
1147  memcpy(buf, &fpregs, size);
1148  return size;
1149 #elif __i386__
1150 #if !__ANDROID__
1151  struct user_fpxregs_struct fpxregs;
1152  ret = rz_debug_ptrace(dbg, PTRACE_GETFPXREGS, pid, NULL, &fpxregs);
1153  if (ret == 0) {
1154  if (showfpu) {
1155  print_fpu((void *)&fpxregs);
1156  }
1157  size = RZ_MIN(sizeof(fpxregs), size);
1158  memcpy(buf, &fpxregs, size);
1159  return size;
1160  } else {
1161  ret = rz_debug_ptrace(dbg, PTRACE_GETFPREGS, pid, NULL, &fpregs);
1162  if (showfpu) {
1163  print_fpu((void *)&fpregs);
1164  }
1165  if (ret != 0) {
1166  rz_sys_perror("PTRACE_GETFPREGS");
1167  return false;
1168  }
1169  size = RZ_MIN(sizeof(fpregs), size);
1170  memcpy(buf, &fpregs, size);
1171  return size;
1172  }
1173 #else
1174  ret = rz_debug_ptrace(dbg, PTRACE_GETFPREGS, pid, NULL, &fpregs);
1175  if (showfpu) {
1176  print_fpu((void *)&fpregs);
1177  }
1178  if (ret != 0) {
1179  rz_sys_perror("PTRACE_GETFPREGS");
1180  return false;
1181  }
1182  size = RZ_MIN(sizeof(fpregs), size);
1183  memcpy(buf, &fpregs, size);
1184  return size;
1185 #endif // !__ANDROID__
1186 #endif // __i386__
1187  }
1188  }
1189 #else
1190 #warning getfpregs not implemented for this platform
1191 #endif
1192  break;
1193  case RZ_REG_TYPE_SEG:
1194  case RZ_REG_TYPE_FLG:
1195  case RZ_REG_TYPE_GPR: {
1197  memset(&regs, 0, sizeof(regs));
1198  memset(buf, 0, size);
1199 #if (__arm64__ || __aarch64__ || __s390x__) && defined(PTRACE_GETREGSET)
1200  struct iovec io = {
1201  .iov_base = &regs,
1202  .iov_len = sizeof(regs)
1203  };
1204  ret = rz_debug_ptrace(dbg, PTRACE_GETREGSET, pid, 1, &io);
1205  // ret = ptrace (PTRACE_GETREGSET, pid, (void*)(size_t)(NT_PRSTATUS), NULL); // &io);
1206  if (ret != 0) {
1207  rz_sys_perror("PTRACE_GETREGSET");
1208  return false;
1209  }
1210 #elif __BSD__ && (__POWERPC__ || __sparc__)
1211  ret = rz_debug_ptrace(dbg, PTRACE_GETREGS, pid, &regs, NULL);
1212 #else
1213  /* linux -{arm/mips/riscv/x86/x86_64} */
1214  ret = rz_debug_ptrace(dbg, PTRACE_GETREGS, pid, NULL, &regs);
1215 #endif
1216  /*
1217  * if perror here says 'no such process' and the
1218  * process exists still.. is because there's a missing call
1219  * to 'wait'. and the process is not yet available to accept
1220  * more ptrace queries.
1221  */
1222  if (ret != 0) {
1223  rz_sys_perror("PTRACE_GETREGS");
1224  return false;
1225  }
1226  size = RZ_MIN(sizeof(regs), size);
1227  memcpy(buf, &regs, size);
1228  return size;
1229  } break;
1230  case RZ_REG_TYPE_YMM: {
1231 #if HAVE_YMM && __x86_64__ && defined(PTRACE_GETREGSET)
1232  ut32 ymm_space[128]; // full ymm registers
1233  struct _xstate xstate;
1234  struct iovec iov;
1235  iov.iov_base = &xstate;
1236  iov.iov_len = sizeof(struct _xstate);
1238  if (ret == -1) {
1239  return false;
1240  }
1241  // stitch together xstate.fpstate._xmm and xstate.ymmh assuming LE
1242  int ri, rj;
1243  for (ri = 0; ri < 16; ri++) {
1244  for (rj = 0; rj < 4; rj++) {
1245 #ifdef __ANDROID__
1246  ymm_space[ri * 8 + rj] = ((struct _libc_fpstate *)&xstate.fpstate)->_xmm[ri].element[rj];
1247 #else
1248  ymm_space[ri * 8 + rj] = xstate.fpstate._xmm[ri].element[rj];
1249 #endif
1250  }
1251  for (rj = 0; rj < 4; rj++) {
1252  ymm_space[ri * 8 + (rj + 4)] = xstate.ymmh.ymmh_space[ri * 4 + rj];
1253  }
1254  }
1255  size = RZ_MIN(sizeof(ymm_space), size);
1256  memcpy(buf, &ymm_space, size);
1257  return size;
1258 #endif
1259  return false;
1260  } break;
1261  }
1262  return false;
1263 }
static char * regs[]
Definition: analysis_sh.c:203
#define RZ_DEBUG_REG_T
Definition: bsd_debug.h:8
uint32_t ut32
voidpf void uLong size
Definition: ioapi.h:138
return memset(p, 0, total)
long rz_debug_ptrace_get_x86_xstate(RzDebug *dbg, pid_t pid, struct iovec *iov)
Definition: linux_debug.c:50
static void print_fpu(void *f)
Definition: linux_debug.c:995
@ RZ_REG_TYPE_SEG
Definition: rz_reg.h:28
@ RZ_REG_TYPE_MMX
Definition: rz_reg.h:24
@ RZ_REG_TYPE_GPR
Definition: rz_reg.h:21
@ RZ_REG_TYPE_YMM
Definition: rz_reg.h:26
@ RZ_REG_TYPE_FLG
Definition: rz_reg.h:27
@ RZ_REG_TYPE_FPU
Definition: rz_reg.h:23
@ RZ_REG_TYPE_DRX
Definition: rz_reg.h:22
@ RZ_REG_TYPE_XMM
Definition: rz_reg.h:25
#define rz_offsetof(type, member)
Definition: rz_types.h:360
#define RZ_MIN(x, y)
@ PTRACE_GETREGS
Definition: sftypes.h:598
@ PTRACE_GETFPREGS
Definition: sftypes.h:608
@ PTRACE_GETFPXREGS
Definition: sftypes.h:626
@ PTRACE_PEEKUSER
Definition: sftypes.h:568
#define a(i)
Definition: sha256.c:41
Definition: sftypes.h:73
static uv_buf_t iov
Definition: main.c:15

◆ linux_reg_write()

int linux_reg_write ( RzDebug dbg,
int  type,
const ut8 buf,
int  size 
)

Definition at line 1265 of file linux_debug.c.

1265  {
1266  int pid = dbg->tid;
1267 
1268  if (type == RZ_REG_TYPE_DRX) {
1269 #if !__ANDROID__ && (__i386__ || __x86_64__)
1270  int i;
1271  long *val = (long *)buf;
1272  for (i = 0; i < 8; i++) { // DR0-DR7
1273  if (i == 4 || i == 5) {
1274  continue;
1275  }
1276  if (rz_debug_ptrace(dbg, PTRACE_POKEUSER, pid,
1277  (void *)rz_offsetof(struct user, u_debugreg[i]), (rz_ptrace_data_t)val[i])) {
1278  eprintf("ptrace error for dr %d\n", i);
1279  rz_sys_perror("ptrace POKEUSER");
1280  }
1281  }
1282  return sizeof(RZ_DEBUG_REG_T);
1283 #else
1284  return false;
1285 #endif
1286  }
1287  if (type == RZ_REG_TYPE_GPR) {
1288 #if __arm64__ || __aarch64__ || __s390x__
1289  struct iovec io = {
1290  .iov_base = (void *)buf,
1291  .iov_len = sizeof(RZ_DEBUG_REG_T)
1292  };
1293  int ret = rz_debug_ptrace(dbg, PTRACE_SETREGSET, pid, (void *)(size_t)NT_PRSTATUS, (rz_ptrace_data_t)(size_t)&io);
1294 #elif __POWERPC__ || __sparc__
1295  int ret = rz_debug_ptrace(dbg, PTRACE_SETREGS, pid, buf, NULL);
1296 #else
1297  int ret = rz_debug_ptrace(dbg, PTRACE_SETREGS, pid, 0, (void *)buf);
1298 #endif
1299 #if DEAD_CODE
1300  if (size > sizeof(RZ_DEBUG_REG_T)) {
1301  size = sizeof(RZ_DEBUG_REG_T);
1302  }
1303 #endif
1304  if (ret == -1) {
1305  rz_sys_perror("reg_write");
1306  return false;
1307  }
1308  return true;
1309  }
1310  if (type == RZ_REG_TYPE_FPU) {
1311 #if __i386__ || __x86_64__
1312  int ret = rz_debug_ptrace(dbg, PTRACE_SETFPREGS, pid, 0, (void *)buf);
1313  return (ret != 0) ? false : true;
1314 #endif
1315  }
1316  return false;
1317 }
ut16 val
Definition: armass64_const.h:6
#define false
#define NT_PRSTATUS
Definition: common.h:393
@ PTRACE_POKEUSER
Definition: sftypes.h:580
@ PTRACE_SETFPREGS
Definition: sftypes.h:613
@ PTRACE_SETREGS
Definition: sftypes.h:603

References dbg, eprintf, false, i, NT_PRSTATUS, NULL, pid, PTRACE_POKEUSER, PTRACE_SETFPREGS, PTRACE_SETREGS, RZ_DEBUG_REG_T, rz_offsetof, RZ_REG_TYPE_DRX, RZ_REG_TYPE_FPU, RZ_REG_TYPE_GPR, rz_sys_perror, rz_debug_t::tid, type, and val.

◆ linux_select()

bool linux_select ( RzDebug dbg,
int  pid,
int  tid 
)

Definition at line 444 of file linux_debug.c.

444  {
445  if (dbg->pid != -1 && dbg->pid != pid) {
447  }
448  return linux_attach(dbg, tid);
449 }
bool linux_attach_new_process(RzDebug *dbg, int pid)
Definition: linux_debug.c:451

References dbg, linux_attach(), linux_attach_new_process(), rz_debug_t::pid, and pid.

◆ linux_set_options()

bool linux_set_options ( RzDebug dbg,
int  pid 
)

Definition at line 383 of file linux_debug.c.

383  {
384  int traceflags = 0;
385  traceflags |= PTRACE_O_TRACEFORK;
386  traceflags |= PTRACE_O_TRACEVFORK;
387  traceflags |= PTRACE_O_TRACECLONE;
388  if (dbg->trace_forks) {
389  traceflags |= PTRACE_O_TRACEVFORKDONE;
390  }
391  if (dbg->trace_execs) {
392  traceflags |= PTRACE_O_TRACEEXEC;
393  }
394  if (dbg->trace_aftersyscall) {
395  traceflags |= PTRACE_O_TRACEEXIT;
396  }
397  /* SIGTRAP | 0x80 on signal handler .. not supported on all archs */
398  traceflags |= PTRACE_O_TRACESYSGOOD;
399 
400  // PTRACE_SETOPTIONS can fail because of the asynchronous nature of ptrace
401  // If the target is traced, the loop will always end with success
402  while (rz_debug_ptrace(dbg, PTRACE_SETOPTIONS, pid, 0, (rz_ptrace_data_t)(size_t)traceflags) == -1) {
403  void *bed = rz_cons_sleep_begin();
404  usleep(1000);
405  rz_cons_sleep_end(bed);
406  }
407  return true;
408 }
int trace_execs
Definition: rz_debug.h:264
int trace_aftersyscall
Definition: rz_debug.h:265
int trace_forks
Definition: rz_debug.h:263

References dbg, pid, rz_cons_sleep_begin(), rz_cons_sleep_end(), rz_debug_t::trace_aftersyscall, rz_debug_t::trace_execs, and rz_debug_t::trace_forks.

Referenced by linux_add_new_thread(), and linux_attach_single_pid().

◆ linux_step()

int linux_step ( RzDebug dbg)

Definition at line 369 of file linux_debug.c.

369  {
370  int ret = false;
371  int pid = dbg->tid;
372  ret = rz_debug_ptrace(dbg, PTRACE_SINGLESTEP, pid, 0, 0);
373  // XXX(jjd): why?? //linux_handle_signals (dbg);
374  if (ret == -1) {
375  perror("native-singlestep");
376  ret = false;
377  } else {
378  ret = true;
379  }
380  return ret;
381 }
@ PTRACE_SINGLESTEP
Definition: sftypes.h:593

References dbg, pid, PTRACE_SINGLESTEP, and rz_debug_t::tid.

◆ linux_stop_threads()

bool linux_stop_threads ( RzDebug dbg,
int  except 
)

Definition at line 660 of file linux_debug.c.

660  {
661  bool ret = true;
662  if (dbg->threads) {
663  RzDebugPid *th;
664  RzListIter *it;
665  rz_list_foreach (dbg->threads, it, th) {
666  if (th->pid && th->pid != except) {
667  if (!linux_stop_thread(dbg, th->pid)) {
668  ret = false;
669  }
670  }
671  }
672  }
673  return ret;
674 }
static bool linux_stop_thread(RzDebug *dbg, int tid)
Definition: linux_debug.c:640

References dbg, linux_stop_thread(), rz_debug_pid_t::pid, and rz_debug_t::threads.

◆ linux_thread_list()

RzList* linux_thread_list ( RzDebug dbg,
int  pid,
RzList list 
)

Definition at line 875 of file linux_debug.c.

875  {
876  int i = 0, thid = 0;
877  char *ptr, buf[PATH_MAX];
878  RzDebugPid *pid_info = NULL;
879  ut64 pc = 0;
880  int prev_tid = dbg->tid;
881 
882  if (!pid) {
884  return NULL;
885  }
886 
888  /* if this process has a task directory, use that */
889  snprintf(buf, sizeof(buf), "/proc/%d/task", pid);
890  if (rz_file_is_directory(buf)) {
891  struct dirent *de;
892  DIR *dh = opendir(buf);
893  // Update the process' memory maps to set correct paths
895  while ((de = readdir(dh))) {
896  if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
897  continue;
898  }
899  int tid = atoi(de->d_name);
900  char info[PATH_MAX];
901  int uid = 0;
902  if (!procfs_pid_slurp(tid, "status", info, sizeof(info))) {
903  ptr = strstr(info, "Uid:");
904  if (ptr) {
905  uid = atoi(ptr + 4);
906  }
907  ptr = strstr(info, "Tgid:");
908  if (ptr) {
909  int tgid = atoi(ptr + 5);
910  if (tgid != pid) {
911  /* Ignore threads that aren't in the pid's thread group */
912  continue;
913  }
914  }
915  }
916 
917  // Switch to the currently inspected thread to get it's program counter
918  if (dbg->tid != tid) {
920  dbg->tid = tid;
921  }
922 
924  pc = rz_debug_reg_get(dbg, "PC");
925 
926  if (!procfs_pid_slurp(tid, "status", info, sizeof(info))) {
927  // Get information about pid (status, pc, etc.)
928  pid_info = fill_pid_info(info, NULL, tid);
929  pid_info->pc = pc;
930  } else {
931  pid_info = rz_debug_pid_new(NULL, tid, uid, 's', pc);
932  }
933  rz_list_append(list, pid_info);
934  dbg->n_threads++;
935  }
936  closedir(dh);
937  // Return to the original thread
938  linux_attach_single_pid(dbg, prev_tid);
939  dbg->tid = prev_tid;
941  } else {
942  /* Some linux configurations might hide threads from /proc, use this workaround instead */
943 #undef MAXPID
944 #define MAXPID 99999
945  /* otherwise, brute force the pids */
946  for (i = pid; i < MAXPID; i++) { // XXX
947  if (procfs_pid_slurp(i, "status", buf, sizeof(buf)) == -1) {
948  continue;
949  }
950  int uid = 0;
951  /* look for a thread group id */
952  ptr = strstr(buf, "Uid:");
953  if (ptr) {
954  uid = atoi(ptr + 4);
955  }
956  ptr = strstr(buf, "Tgid:");
957  if (ptr) {
958  int tgid = atoi(ptr + 5);
959 
960  /* if it is not in our thread group, we don't want it */
961  if (tgid != pid) {
962  continue;
963  }
964 
965  if (procfs_pid_slurp(i, "comm", buf, sizeof(buf)) == -1) {
966  /* fall back to auto-id */
967  snprintf(buf, sizeof(buf), "thread_%d", thid++);
968  }
969  rz_list_append(list, rz_debug_pid_new(buf, i, uid, 's', 0));
970  }
971  }
972  }
973  return list;
974 }
RZ_API bool rz_debug_map_sync(RzDebug *dbg)
Definition: dmap.c:33
RZ_API int rz_debug_reg_sync(RzDebug *dbg, int type, int write)
Definition: dreg.c:9
#define MAXPID
RZ_API bool rz_file_is_directory(const char *str)
Definition: file.c:167
int n_threads
Definition: rz_debug.h:250

References dirent::d_name, dbg, fill_pid_info(), i, info(), linux_attach_single_pid(), list(), MAXPID, rz_debug_t::n_threads, NULL, rz_debug_pid_t::pc, pc, pid, procfs_pid_slurp(), readdir, rz_debug_map_sync(), rz_debug_pid_free(), rz_debug_pid_new(), rz_debug_reg_get(), rz_debug_reg_sync(), rz_file_is_directory(), rz_list_append(), rz_list_free(), RZ_REG_TYPE_GPR, snprintf, rz_debug_t::tid, and ut64().

Referenced by get_pid_thread_list(), and linux_info().

◆ match_pid()

int match_pid ( const void *  pid_o,
const void *  th_o 
)

Definition at line 608 of file linux_debug.c.

608  {
609  int pid = *(int *)pid_o;
610  RzDebugPid *th = (RzDebugPid *)th_o;
611  return (pid == th->pid) ? 0 : 1;
612 }

References rz_debug_pid_t::pid, and pid.

Referenced by linux_attach(), and linux_dbg_wait().