/* peek.c - print RIP/RBX/RSP/RDI of every thread of a process (root). usage: peek PID [lo_off hi_off] (offsets from the libcuda r-xp base) Flags threads whose RIP is inside [base+lo, base+hi) with SPIN. */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include int main(int argc, char **argv) { if (argc < 2) { fprintf(stderr, "usage: peek PID [lo_off hi_off]\n"); return 1; } int pid = atoi(argv[1]); unsigned long lo = 0x23f700, hi = 0x23fd10; if (argc >= 4) { lo = strtoul(argv[2], 0, 16); hi = strtoul(argv[3], 0, 16); } char path[256]; snprintf(path, sizeof path, "/proc/%d/maps", pid); FILE *f = fopen(path, "r"); if (!f) { perror("maps"); return 1; } unsigned long base = 0; char line[512]; while (fgets(line, sizeof line, f)) { if (strstr(line, "libcuda") && strstr(line, "r-xp")) { unsigned long a, b, off; char perms[8], dev[16], name[256]; unsigned long ino; if (sscanf(line, "%lx-%lx %7s %lx %15s %lu %255s", &a, &b, perms, &off, dev, &ino, name) >= 6) { base = a - off; break; } } } fclose(f); printf("libcuda base=0x%lx\n", base); snprintf(path, sizeof path, "/proc/%d/task", pid); DIR *d = opendir(path); if (!d) { perror("task"); return 1; } struct dirent *e; while ((e = readdir(d))) { if (e->d_name[0] == '.') continue; int tid = atoi(e->d_name); if (ptrace(PTRACE_ATTACH, tid, 0, 0)) { printf("tid %d attach fail\n", tid); continue; } int st; waitpid(tid, &st, 0); struct user_regs_struct r; struct iovec io = { &r, sizeof r }; if (ptrace(PTRACE_GETREGSET, tid, (void *)1, &io)) { printf("tid %d getregs fail\n", tid); ptrace(PTRACE_DETACH, tid, 0, 0); continue; } printf("tid %d rip=0x%llx rsp=0x%llx rbx=0x%llx rdi=0x%llx%s\n", tid, (unsigned long long)r.rip, (unsigned long long)r.rsp, (unsigned long long)r.rbx, (unsigned long long)r.rdi, (r.rip >= base + lo && r.rip < base + hi) ? " SPIN" : ""); ptrace(PTRACE_DETACH, tid, 0, 0); } closedir(d); return 0; }