#include #include #include #include #include #include #include #include #include #include #ifdef __GLIBC__ /* glibc */ #include #else /* bionic/android */ #include #endif #define PID_INVALID ((pid_t)-1) #define TRY(e) do { if((e)==-1) { fprintf(stderr, "Error:%s:%s\n", #e, strerror(errno)); exit(EXIT_FAILURE); } } while(0) #if defined(__x86_64__) typedef struct user_regs_struct pt_regs_t; static void print_regs(FILE *out, const pt_regs_t *regs, const char *prefix_str) { const struct { const char *n; ptrdiff_t o; } r[] = { { "rax", offsetof(pt_regs_t, rax), }, { "rbx", offsetof(pt_regs_t, rbx), }, { "rcx", offsetof(pt_regs_t, rcx), }, { "rdx", offsetof(pt_regs_t, rdx), }, { "rsi", offsetof(pt_regs_t, rsi), }, { "rdi", offsetof(pt_regs_t, rdi), }, { "rbp", offsetof(pt_regs_t, rbp), }, { "rsp", offsetof(pt_regs_t, rsp), }, { "r8", offsetof(pt_regs_t, r8), }, { "r9", offsetof(pt_regs_t, r9), }, { "r10", offsetof(pt_regs_t, r10), }, { "r11", offsetof(pt_regs_t, r11), }, { "r12", offsetof(pt_regs_t, r12), }, { "r13", offsetof(pt_regs_t, r13), }, { "r14", offsetof(pt_regs_t, r14), }, { "r15", offsetof(pt_regs_t, r15), }, { "rip", offsetof(pt_regs_t, rip), }, { "eflags", offsetof(pt_regs_t, eflags), }, { "cs", offsetof(pt_regs_t, cs), }, { "ss", offsetof(pt_regs_t, ss), }, { "ds", offsetof(pt_regs_t, ds), }, { "es", offsetof(pt_regs_t, es), }, { "fs", offsetof(pt_regs_t, fs), }, { "gs", offsetof(pt_regs_t, gs), }, }; unsigned i; if(!prefix_str) prefix_str=""; for(i=0;i0) { linkpath[len]=0; fprintf(out, "exe: \"%s\"\n", linkpath); } snprintf(procpath, sizeof procpath, "/proc/%lu/cmdline", (long)progpid); f=fopen(procpath, "rb"); len=fread(cmdline, 1, sizeof cmdline-1, f); if(ferror(f)) { perror(procpath); fclose(f); exit(EXIT_FAILURE); } fclose(f); cmdline[len]=0; fprintf(out, "argv[0]: \"%s\"\n", cmdline); } static void dumpregs(FILE *out, pid_t progpid) { int status; pt_regs_t regs; if(progpid==getpid()) { fprintf(stderr, "Error:Cannot dump myself!\n"); exit(EXIT_FAILURE); } TRY(ptrace(PTRACE_ATTACH, progpid, NULL, NULL)); TRY(waitpid(progpid, &status, 0)); TRY(ptrace(PTRACE_GETREGS, progpid, NULL, ®s)); print_regs(out, ®s, "\t"); TRY(ptrace(PTRACE_DETACH, progpid, NULL, NULL)); } int main(int argc, char **argv) { pid_t progpid=PID_INVALID; int dumpprogname_fl=1; int c; FILE *out=stdout; while((c=getopt(argc, argv, "hp:r"))>0) switch(c) { case 'r': /* dump regs only */ dumpprogname_fl=0; break; case 'p': progpid=strtol(optarg, 0, 10); break; default: usage: case 'h': { const char *progname; progname=strrchr(argv[0], '/'); if(!progname) progname=argv[0]; fprintf(stderr, "usage: %s [-h] [-p ]\n", progname); fprintf(stderr, " -h Help.\n"); fprintf(stderr, " -p

Process to dump.\n"); fprintf(stderr, " -r Print only register dump.\n"); return EXIT_FAILURE; } } if(progpid==PID_INVALID) goto usage; fprintf(out, "pid: %ld\n", (long)progpid); if(dumpprogname_fl) dumpprogname(out, progpid); dumpregs(out, progpid); return 0; }