9a04a665490f22468d8b1a6faadc21aad4751752
[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 [-hna] PID\n");
15 }
16
17 static int dumpstack(pid_t pid, int resolve)
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: %s\n", unw_strerror(s));
31         rv = 1;
32         goto out;
33     }
34     do {
35         if(resolve && (!(s = unw_get_proc_name(&uw, pnm, sizeof(pnm), &pcoff)) || (s == -UNW_ENOMEM))) {
36             pnm[sizeof(pnm) - 1] = 0;
37             if(resolve == 2) {
38                 unw_get_reg(&uw, UNW_REG_IP, &reg);
39                 printf("%s(%jx)+%jx\n", pnm, (intmax_t)(reg - pcoff), (intmax_t)pcoff);
40             } else {
41                 printf("%s+%jx\n", pnm, (intmax_t)pcoff);
42             }
43         } else {
44             unw_get_reg(&uw, UNW_REG_IP, &reg);
45             printf("%jx\n", (intmax_t)reg);
46         }
47     } while((s = unw_step(&uw)) > 0);
48     if(s < 0) {
49         fprintf(stderr, "pstack: step: %s\n", unw_strerror(s));
50     }
51 out:
52     _UPT_destroy(ptd);
53     unw_destroy_addr_space(rps);
54     return(rv);
55 }
56
57 int main(int argc, char **argv)
58 {
59     int c, s, res;
60     pid_t pid;
61     
62     res = 1;
63     while((c = getopt(argc, argv, "hna")) != -1) {
64         switch(c) {
65         case 'h':
66             usage(stdout);
67             exit(0);
68         case 'n':
69             res = 0;
70             break;
71         case 'a':
72             res = 2;
73             break;
74         default:
75             usage(stderr);
76             exit(1);
77         }
78     }
79     if(argc - optind < 1) {
80         usage(stderr);
81         exit(1);
82     }
83     pid = atoi(argv[optind]);
84     if(ptrace(PTRACE_ATTACH, pid, NULL, NULL)) {
85         fprintf(stderr, "pstack: attach %i: %s\n", pid, strerror(errno));
86         exit(1);
87     }
88     while(1) {
89         if(waitpid(pid, &s, 0) < 0) {
90             fprintf(stderr, "pstack: wait: %s\n", strerror(errno));
91             exit(1);
92         }
93         if(WIFSTOPPED(s))
94             break;
95     }
96     dumpstack(pid, res);
97     if(ptrace(PTRACE_DETACH, pid, NULL, NULL)) {
98         fprintf(stderr, "pstack: detach: %s\n", strerror(errno));
99     }
100     return(0);
101 }
102
103 /*
104  * Local Variables:
105  * compile-command: "gcc -Wall -g -o pstack pstack.c -lunwind-ptrace -lunwind-x86_64"
106  * End:
107  */