anndl: Fixed a couple of bugs.
[utils.git] / pstack.c
1 #include <stdlib.h>
2 #include <stdint.h>
3 #include <stdio.h>
4 #include <unistd.h>
5 #include <string.h>
6 #include <errno.h>
7 #include <sys/ptrace.h>
8 #include <sys/wait.h>
9 #include <libunwind.h>
10 #include <libunwind-ptrace.h>
11
12 static void usage(FILE *out)
13 {
14     fprintf(out, "usage: pstack [-h] PID\n");
15 }
16
17 static int dumpstack(pid_t pid)
18 {
19     int rv, s;
20     unw_addr_space_t rps;
21     unw_cursor_t uw;
22     unw_word_t reg, pcoff;
23     void *ptd;
24     char pnm[64];
25     
26     rps = unw_create_addr_space(&_UPT_accessors, 0);
27     ptd = _UPT_create(pid);
28     rv = 0;
29     if((s = unw_init_remote(&uw, rps, ptd)) != 0) {
30         fprintf(stderr, "pstack: init_remote: %i\n", s);
31         rv = 1;
32         goto out;
33     }
34     do {
35         if(!(s = unw_get_proc_name(&uw, pnm, sizeof(pnm), &pcoff)) || (s == -UNW_ENOMEM)) {
36             pnm[sizeof(pnm) - 1] = 0;
37             printf("%s+%jx\n", pnm, (intmax_t)pcoff);
38         } else {
39             unw_get_reg(&uw, UNW_REG_IP, &reg);
40             printf("%jx\n", (intmax_t)reg);
41         }
42     } while((s = unw_step(&uw)) > 0);
43     if(s < 0) {
44         fprintf(stderr, "pstack: step: %i\n", s);
45     }
46 out:
47     _UPT_destroy(ptd);
48     unw_destroy_addr_space(rps);
49     return(rv);
50 }
51
52 int main(int argc, char **argv)
53 {
54     int c, s;
55     pid_t pid;
56     
57     while((c = getopt(argc, argv, "h")) != -1) {
58         switch(c) {
59         case 'h':
60             usage(stdout);
61             exit(0);
62         default:
63             usage(stderr);
64             exit(1);
65         }
66     }
67     if(argc - optind < 1) {
68         usage(stderr);
69         exit(1);
70     }
71     pid = atoi(argv[optind]);
72     if(ptrace(PTRACE_ATTACH, pid, NULL, NULL)) {
73         fprintf(stderr, "pstack: attach %i: %s\n", pid, strerror(errno));
74         exit(1);
75     }
76     while(1) {
77         if(waitpid(pid, &s, 0) < 0) {
78             fprintf(stderr, "pstack: wait: %s\n", strerror(errno));
79             exit(1);
80         }
81         if(WIFSTOPPED(s))
82             break;
83     }
84     dumpstack(pid);
85     if(ptrace(PTRACE_DETACH, pid, NULL, NULL)) {
86         fprintf(stderr, "pstack: detach: %s\n", strerror(errno));
87     }
88     return(0);
89 }
90
91 /*
92  * Local Variables:
93  * compile-command: "gcc -Wall -g -o pstack pstack.c -lunwind-ptrace -lunwind-x86_64"
94  * End:
95  */