diff --git a/libr/core/cmd.c b/libr/core/cmd.c index c0bab2e646..6f8b5cea7c 100644 --- a/libr/core/cmd.c +++ b/libr/core/cmd.c @@ -4555,13 +4555,12 @@ static int cmd_debug(void *data, const char *input) { } else r_debug_trace_list (core->dbg, -1); break; case 'd': - eprintf ("TODO: dd: file descriptors\n"); switch (input[1]) { - case 0: - // r_debug_desc_list() + case '\0': + r_debug_desc_list (core->dbg, 0); break; case '*': - // r_debug_desc_list(1) + r_debug_desc_list (core->dbg, 1); break; case 's': // r_debug_desc_seek() @@ -4581,6 +4580,13 @@ static int cmd_debug(void *data, const char *input) { case ' ': // open file break; + case '?': + default: + r_cons_printf ("Usage: dd[*sdrw-?]\n" + " dd list filedescriptors\n" + " dd* list filedescriptors (in radare commands)\n" + " dd? show this help\n"); + break; } break; case 's': diff --git a/libr/debug/desc.c b/libr/debug/desc.c index 7c05a84aff..3bcb072693 100644 --- a/libr/debug/desc.c +++ b/libr/debug/desc.c @@ -4,6 +4,26 @@ #include +R_API RDebugDesc *r_debug_desc_new (int fd, char* path, int perm, int type, int off) { + RDebugDesc *desc = R_NEW (RDebugDesc); + if (desc) { + desc->fd = fd; + desc->path = strdup (path); + desc->perm = perm; + desc->type = type; + desc->off = off; + } + return desc; +} + +R_API void r_debug_desc_free (RDebugDesc *p) { + if (p) { + if (p->path) + free (p->path); + free (p); + } +} + R_API int r_debug_desc_open(RDebug *dbg, const char *path) { if (dbg && dbg->h && dbg->h->desc.open) return dbg->h->desc.open (path); @@ -42,8 +62,25 @@ R_API int r_debug_desc_write(RDebug *dbg, int fd, ut64 addr, int len) { R_API int r_debug_desc_list(RDebug *dbg, int rad) { int count = 0; - // callback or rlist? i would prefer rlist here.. - //RList *list = dbg->h->desc.list (); - // TODO: loop here + RList *list; + RListIter *iter; + RDebugDesc *p; + + if (rad) { + if (dbg && dbg->printf) + dbg->printf ("TODO \n"); + } else { + if (dbg && dbg->h && dbg->h->desc.list) { + list = dbg->h->desc.list (dbg->pid); + r_list_foreach (list, iter, p) { + dbg->printf ("%i 0x%"PFMT64x" %c%c%c %s\n", p->fd, p->off, + (p->perm & R_IO_READ)?'r':'-', + (p->perm & R_IO_WRITE)?'w':'-', + p->type, p->path); + } + r_list_destroy (list); + free (list); + } + } return count; } diff --git a/libr/debug/p/debug_native.c b/libr/debug/p/debug_native.c index 221cb63cc7..a6ac770f76 100644 --- a/libr/debug/p/debug_native.c +++ b/libr/debug/p/debug_native.c @@ -1493,7 +1493,7 @@ static RList *r_debug_native_map_get(RDebug *dbg) { int i, perm, unk = 0; char *pos_c; char path[1024], line[1024]; - char region[100], region2[100], perms[5], null[16]; + char region[100], region2[100], perms[5]; FILE *fd; if (dbg->pid == -1) { eprintf ("r_debug_native_map_get: No selected pid (-1)\n"); @@ -1532,6 +1532,7 @@ static RList *r_debug_native_map_get(RDebug *dbg) { if (pos_c) strncpy (path, pos_c, sizeof (path)-1); else path[0]='\0'; #else + char null[16]; sscanf (line, "%s %s %s %s %s %s", ®ion[2], perms, null, null, null, path); @@ -1733,7 +1734,9 @@ static int r_debug_native_kill(RDebug *dbg, boolt thread, int sig) { #endif } +struct r_debug_desc_plugin_t r_debug_desc_plugin_native; static int r_debug_native_init(RDebug *dbg) { + dbg->h->desc = r_debug_desc_plugin_native; #if __WINDOWS__ return w32_dbg_init (); #else @@ -1764,6 +1767,121 @@ static int r_debug_native_bp(void *user, int add, ut64 addr, int hw, int rwx) { return R_FALSE; } +static RList *r_debug_desc_native_list (int pid) { + RList *ret; + RDebugDesc *desc; + int perm, type; +#if __KFBSD__ + int mib[4]; + size_t len; + char *buf, *bp, *eb; + struct kinfo_file *kve; + + len = 0; + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_FILEDESC; + mib[3] = pid; + + if (sysctl(mib, 4, NULL, &len, NULL, 0) != 0) + return NULL; + len = len * 4 / 3; + buf = malloc(len); + if (buf == NULL) + return (NULL); + if (sysctl(mib, 4, buf, &len, NULL, 0) != 0) { + free (buf); + return NULL; + } + bp = buf; + eb = buf + len; + ret = r_list_new (); + if (ret) { + ret->free = (RListFree) r_debug_desc_free; + while (bp < eb) { + kve = (struct kinfo_file *)(uintptr_t)bp; + bp += kve->kf_structsize; + if (kve->kf_fd < 0) // Skip root and cwd. We need it ?? + continue; + switch (kve->kf_vnode_type) { + case KF_VTYPE_VREG: type = 'r'; break; + case KF_VTYPE_VDIR: type = 'd'; break; + case KF_VTYPE_VBLK: type = 'b'; break; + case KF_VTYPE_VCHR: type = 'c'; break; + case KF_VTYPE_VLNK: type = 'l'; break; + case KF_VTYPE_VSOCK: type = 's'; break; + case KF_VTYPE_VFIFO: type = 'f'; break; + case KF_VTYPE_VBAD: type = 'x'; break; + case KF_VTYPE_VNON: + case KF_VTYPE_UNKNOWN: + default: type = '-'; break; + } + perm = (kve->kf_flags & KF_FLAG_READ)?R_IO_READ:0; + perm |= (kve->kf_flags & KF_FLAG_WRITE)?R_IO_WRITE:0; + desc = r_debug_desc_new (kve->kf_fd, kve->kf_path, perm, type, + kve->kf_offset); + if (desc == NULL) + break; + r_list_append (ret, desc); + } + } + free (buf); +#elif __linux__ + char path[1024], file[2048], buf[1024]; + struct dirent *de; + DIR *dd; + struct stat st; + + snprintf (path, sizeof (path), "/proc/%i/fd/", pid); + dd = opendir(path); + if (dd==NULL) { + printf("Cannot open /proc\n"); + return NULL; + } + + ret = r_list_new (); + if (ret) { + ret->free = (RListFree) r_debug_desc_free; + while((de = (struct dirent *)readdir(dd))) { + if (de->d_name[0]=='.') + continue; + strncpy (file, path, sizeof (file)); + strncat (file, de->d_name, sizeof (file)); + memset (buf, 0, sizeof (buf)); + readlink(file, buf, sizeof (buf)); + type = perm = 0; + if (stat(file, &st) != -1) { + type = st.st_mode & S_IFIFO ? 'P': + st.st_mode & S_IFSOCK ? 'S': + st.st_mode & S_IFCHR ? 'C':'-'; + } + if (lstat(path, &st) != -1) { + if (st.st_mode & S_IRUSR) + perm |= R_IO_READ; + if (st.st_mode & S_IWUSR) + perm |= R_IO_WRITE; + } + //TODO: Offset + desc = r_debug_desc_new (atoi (de->d_name), buf, perm, type, 0); + if (desc == NULL) + break; + r_list_append (ret, desc); + } + closedir(dd); + } +#endif + return ret; +} + +static int r_debug_desc_native_open (const char *path) { + return 0; +} + +struct r_debug_desc_plugin_t r_debug_desc_plugin_native = { + .open = r_debug_desc_native_open, + .list = r_debug_desc_native_list, +}; + struct r_debug_plugin_t r_debug_plugin_native = { .name = "native", #if __i386__ diff --git a/libr/include/r_debug.h b/libr/include/r_debug.h index 0f642c02f8..5056b9e798 100644 --- a/libr/include/r_debug.h +++ b/libr/include/r_debug.h @@ -86,6 +86,14 @@ typedef struct r_debug_map_t { int user; } RDebugMap; +typedef struct r_debug_desc_t { + int fd; + char *path; + int perm; + int type; + ut64 off; +} RDebugDesc; + typedef struct r_debug_trace_t { RList *traces; int count; @@ -143,7 +151,7 @@ typedef struct r_debug_desc_plugin_t { int (*write)(int fd, ut64 addr, int len); int (*seek)(int fd, ut64 addr); int (*dup)(int fd, int newfd); - RList* (*list)(); + RList* (*list)(int pid); } RDebugDescPlugin; /* TODO: pass dbg and user data pointer everywhere */ @@ -248,6 +256,8 @@ R_API void r_debug_map_free(RDebugMap *map); R_API void r_debug_map_list(RDebug *dbg, ut64 addr); /* descriptors */ +R_API RDebugDesc *r_debug_desc_new (int fd, char* path, int perm, int type, int off); +R_API void r_debug_desc_free (RDebugDesc *p); R_API int r_debug_desc_open(RDebug *dbg, const char *path); R_API int r_debug_desc_close(RDebug *dbg, int fd); R_API int r_debug_desc_dup(RDebug *dbg, int fd, int newfd);