1 | #include <stdlib.h> |
---|
2 | #include <stdio.h> |
---|
3 | #include <string.h> |
---|
4 | #include <sys/types.h> |
---|
5 | #include <sys/stat.h> |
---|
6 | #include <fcntl.h> |
---|
7 | #include <sys/ptrace.h> |
---|
8 | #include <poll.h> |
---|
9 | #include <errno.h> |
---|
10 | |
---|
11 | #ifndef FALSE |
---|
12 | #define FALSE 0 |
---|
13 | #define TRUE (!FALSE) |
---|
14 | #endif |
---|
15 | |
---|
16 | enum types { |
---|
17 | type_byte, |
---|
18 | type_fdset, |
---|
19 | type_pollfd, |
---|
20 | }; |
---|
21 | |
---|
22 | main(int argc,char **argv) |
---|
23 | { |
---|
24 | const char *arg0=argv[0]; |
---|
25 | int mem_fd,pid,j,first; |
---|
26 | enum types type=type_byte; |
---|
27 | unsigned long offset,count,i,n; |
---|
28 | char mem_file_name[64]; |
---|
29 | unsigned char *buf; |
---|
30 | fd_set *fds; |
---|
31 | struct pollfd *pfd; |
---|
32 | if (argc>3 && !strcmp(argv[1],"-t")) |
---|
33 | { |
---|
34 | if (!strcmp(argv[2],"byte")) |
---|
35 | type=type_byte; |
---|
36 | else if (!strcmp(argv[2],"fdset")) |
---|
37 | type=type_fdset; |
---|
38 | else if (!strcmp(argv[2],"pollfd")) |
---|
39 | type=type_pollfd; |
---|
40 | else |
---|
41 | { |
---|
42 | fprintf(stderr,"Unknown type: %s",argv[2]); |
---|
43 | exit(1); |
---|
44 | } |
---|
45 | argc-=2; |
---|
46 | argv+=2; |
---|
47 | } |
---|
48 | if (argc!=4) |
---|
49 | { |
---|
50 | fprintf(stderr,"Usage: %s [opts] <pid> <offset> <count>\n",arg0); |
---|
51 | exit(1); |
---|
52 | } |
---|
53 | pid=atoi(argv[1]); |
---|
54 | if (pid<=0) |
---|
55 | { |
---|
56 | fprintf(stderr,"Illegal pid: %d\n",pid); |
---|
57 | exit(1); |
---|
58 | } |
---|
59 | offset=strtoul(argv[2],NULL,0); |
---|
60 | if (!offset) |
---|
61 | { |
---|
62 | fprintf(stderr,"Illegal offset: %s\n",argv[2]); |
---|
63 | exit(1); |
---|
64 | } |
---|
65 | count=strtoul(argv[3],NULL,0); |
---|
66 | if (!count) |
---|
67 | { |
---|
68 | fprintf(stderr,"Illegal count: %s\n",argv[3]); |
---|
69 | exit(1); |
---|
70 | } |
---|
71 | switch(type) |
---|
72 | { |
---|
73 | case type_byte: |
---|
74 | n=1; |
---|
75 | break; |
---|
76 | case type_fdset: |
---|
77 | n=sizeof(fd_set); |
---|
78 | break; |
---|
79 | case type_pollfd: |
---|
80 | n=sizeof(struct pollfd); |
---|
81 | break; |
---|
82 | } |
---|
83 | n*=count; |
---|
84 | buf=malloc(n); |
---|
85 | if (!buf) |
---|
86 | { |
---|
87 | fprintf(stderr,"Not enough memory to read %d bytes\n",n); |
---|
88 | exit(1); |
---|
89 | } |
---|
90 | sprintf(mem_file_name,"/proc/%d/mem",pid); |
---|
91 | mem_fd=open(mem_file_name,O_RDONLY); |
---|
92 | if (ptrace(PTRACE_ATTACH,pid,NULL,NULL)<0) |
---|
93 | { |
---|
94 | fprintf(stderr,"ptrace attach: %s\n",strerror(errno)); |
---|
95 | exit(1); |
---|
96 | } |
---|
97 | waitpid(pid,NULL,0); |
---|
98 | lseek(mem_fd,offset,SEEK_SET); |
---|
99 | read(mem_fd,buf,n); |
---|
100 | if (ptrace(PTRACE_DETACH,pid,NULL,NULL)<0) |
---|
101 | { |
---|
102 | fprintf(stderr,"ptrace detach: %s\n",strerror(errno)); |
---|
103 | exit(1); |
---|
104 | } |
---|
105 | close(mem_fd); |
---|
106 | first=TRUE; |
---|
107 | for(i=0;i<count;i++) |
---|
108 | { |
---|
109 | switch(type) |
---|
110 | { |
---|
111 | case type_byte: |
---|
112 | printf("0x%X\n",buf[i]); |
---|
113 | break; |
---|
114 | case type_fdset: |
---|
115 | fds=((fd_set *)buf)+i; |
---|
116 | printf("["); |
---|
117 | for(j=0;j<FD_SETSIZE;j++) |
---|
118 | if (FD_ISSET(j,fds)) |
---|
119 | { |
---|
120 | if (!first) |
---|
121 | putchar(' '); |
---|
122 | printf("%d",j); |
---|
123 | first=FALSE; |
---|
124 | } |
---|
125 | printf("]\n"); |
---|
126 | break; |
---|
127 | case type_pollfd: |
---|
128 | pfd=((struct pollfd *)buf)+i; |
---|
129 | printf("{fd=%d, events=%d, revents=%d}\n",pfd->fd,pfd->events, |
---|
130 | pfd->revents); |
---|
131 | break; |
---|
132 | } |
---|
133 | } |
---|
134 | free(buf); |
---|
135 | } |
---|