1 #include <lib9.h>
2 #include <bio.h>
3 #include <ctype.h>
4 #include "mach.h"
5 #define Extern extern
6 #include "acid.h"
7 #include "../../include/rdbg.h"
8
9 /*
10 * remote kernel debugging
11 */
12
13 enum {
14 chatty = 0
15 };
16
17 static long myreadn(int, void*, long);
18 static int rproto(int, char*, int);
19
20 void
remotemap(Map * m,int i)21 remotemap(Map *m, int i)
22 {
23 setmapio(m, i, remget, remput);
24 }
25
26 /*
27 * send a /proc control message to remote pid,
28 * and await a reply
29 */
30 int
sendremote(int pid,char * msg)31 sendremote(int pid, char *msg)
32 {
33 int tag;
34 char dbg[RDBMSGLEN];
35
36 if(protodebug)
37 fprint(2, "sendremote: pid %d: %s\n", pid, msg);
38 if(strcmp(msg, "startstop") == 0)
39 tag = Tstartstop;
40 else if(strcmp(msg, "waitstop") == 0)
41 tag = Twaitstop;
42 else if(strcmp(msg, "start") == 0)
43 tag = Tstart;
44 else if(strcmp(msg, "stop") == 0)
45 tag = Tstop;
46 else if(strcmp(msg, "kill") == 0)
47 tag = Tkill;
48 else {
49 werrstr("invalid sendremote: %s", msg);
50 return -1;
51 }
52 memset(dbg, 0, sizeof(dbg));
53 dbg[0] = tag;
54 dbg[1] = pid>>24;
55 dbg[2] = pid>>16;
56 dbg[3] = pid>>8;
57 dbg[4] = pid;
58 if(rproto(remfd, dbg, sizeof(dbg)) < 0)
59 return -1;
60 return 0;
61 }
62
63 /*
64 * read a line from /proc/<pid>/<file> into buf
65 */
66 int
remoteio(int pid,char * file,char * buf,int nb)67 remoteio(int pid, char *file, char *buf, int nb)
68 {
69 char dbg[RDBMSGLEN];
70 int tag;
71
72 if(protodebug)
73 fprint(2, "remoteio %d: %s\n", pid, file);
74 memset(buf, 0, nb);
75 if(strcmp(file, "proc") == 0)
76 tag = Tproc;
77 else if(strcmp(file, "status") == 0)
78 tag = Tstatus;
79 else if(strcmp(file, "note") == 0)
80 tag = Trnote;
81 else {
82 werrstr("invalid remoteio: %s", file);
83 return -1;
84 }
85 memset(dbg, 0, sizeof(dbg));
86 dbg[0] = tag;
87 dbg[1] = pid>>24;
88 dbg[2] = pid>>16;
89 dbg[3] = pid>>8;
90 dbg[4] = pid;
91 if(rproto(remfd, dbg, sizeof(dbg)) < 0)
92 return -1;
93 if(nb > sizeof(dbg)-1)
94 nb = sizeof(dbg)-1;
95 memmove(buf, dbg+1, nb);
96 return strlen(buf);
97 }
98
99 int
remget(struct segment * s,ulong addr,long off,char * buf,int size)100 remget(struct segment *s, ulong addr, long off, char *buf, int size)
101 {
102 int n, t;
103 char dbg[RDBMSGLEN];
104
105 if (protodebug)
106 fprint(2, "remget addr %#lux off %#lux\n", addr, off);
107 for (t = 0; t < size; t += n) {
108 n = size;
109 if(n > 9)
110 n = 9;
111 memset(dbg, 0, sizeof(dbg));
112 dbg[0] = Tmget;
113 dbg[1] = off>>24;
114 dbg[2] = off>>16;
115 dbg[3] = off>>8;
116 dbg[4] = off;
117 dbg[5] = n;
118 if(rproto(s->fd, dbg, sizeof(dbg)) < 0) {
119 werrstr("can't read address %#lux: %r", addr);
120 return -1;
121 }
122 memmove(buf, dbg+1, n);
123 buf += n;
124 }
125 return t;
126 }
127
128 int
remput(struct segment * s,ulong addr,long off,char * buf,int size)129 remput(struct segment *s, ulong addr, long off, char *buf, int size)
130 {
131 int n, i, t;
132 char dbg[RDBMSGLEN];
133
134 if (protodebug)
135 fprint(2, "remput addr %#lux off %#lux\n", addr, off);
136 for (t = 0; t < size; t += n) {
137 n = size;
138 if(n > 4)
139 n = 4;
140 memset(dbg, 0, sizeof(dbg));
141 dbg[0] = Tmput;
142 dbg[1] = off>>24;
143 dbg[2] = off>>16;
144 dbg[3] = off>>8;
145 dbg[4] = off;
146 dbg[5] = n;
147 for(i=0; i<n; i++)
148 dbg[6+i] = *buf++;
149 if(rproto(s->fd, dbg, sizeof(dbg)) < 0) {
150 werrstr("can't write address %#lux: %r", addr);
151 return -1;
152 }
153 }
154 return t;
155 }
156
157 int
remcondset(char op,ulong val)158 remcondset(char op, ulong val)
159 {
160 char dbg[RDBMSGLEN];
161
162 if (protodebug)
163 fprint(2, "remcondset op %c val: %#lux\n", op, val);
164 memset(dbg, 0, sizeof(dbg));
165
166 dbg[0] = Tcondbreak;
167 dbg[1] = val>>24;
168 dbg[2] = val>>16;
169 dbg[3] = val>>8;
170 dbg[4] = val;
171 dbg[5] = op;
172 if(rproto(remfd, dbg, sizeof(dbg)) < 0) {
173 werrstr("can't set condbreak: %c %#lux: %r", op, val);
174 return -1;
175 }
176 return 0;
177 }
178
179 int
remcondstartstop(int pid)180 remcondstartstop(int pid)
181 {
182 char dbg[RDBMSGLEN];
183
184 if (protodebug)
185 fprint(2, "remcondstartstop pid %d\n", pid);
186 memset(dbg, 0, sizeof(dbg));
187
188 dbg[0] = Tstartstop;
189 dbg[1] = pid>>24;
190 dbg[2] = pid>>16;
191 dbg[3] = pid>>8;
192 dbg[4] = pid;
193
194 if(rproto(remfd, dbg, sizeof(dbg)) < 0) {
195 werrstr("can't send Tstartstop");
196 return -1;
197 }
198
199 return dbg[1];
200 }
201
202 static int
rproto(int fd,char * buf,int nb)203 rproto(int fd, char *buf, int nb)
204 {
205 int tag;
206
207 if (protodebug) {
208 int i;
209 print("rproto remote write fd %d bytes: %d\n", fd, nb);
210 for (i=0; i < nb; i++) {
211 print(" %2.2ux", buf[i]&0xFF);
212 }
213 print("\n");
214 }
215 tag = buf[0];
216 if(remote_write(fd, buf, nb) != nb ||
217 myreadn(fd, buf, nb) != nb){ /* could set alarm */
218 werrstr("remote i/o: %r");
219 return -1;
220 }
221 if(buf[0] == Rerr){
222 buf[nb-1] = 0;
223 werrstr("remote err: %s", buf+1);
224 return -1;
225 }
226 if(buf[0] != tag+1) {
227 werrstr("remote proto err: %.2ux", buf[0]&0xff);
228 return -1;
229 }
230 if(chatty) {
231 int i;
232 fprint(2, "remote [%d]: ", nb);
233 for(i=0; i<nb; i++)
234 fprint(2, " %.2ux", buf[i]&0xff);
235 fprint(2, "\n");
236 }
237 return nb;
238 }
239
240 /*
241 * this should probably be in lib9 as readn
242 */
243 static long
myreadn(int f,void * av,long n)244 myreadn(int f, void *av, long n)
245 {
246 char *a;
247 long m, t;
248
249 if (protodebug) {
250 print("remote read fd %d bytes: %ld", f, n);
251 }
252 a = av;
253 t = 0;
254 while(t < n){
255 m = remote_read(f, a+t, n-t);
256 if(m < 0){
257 if(t == 0)
258 return m;
259 break;
260 }
261 if (protodebug) {
262 print(" rtn: %ld\n", m);
263 if (m) {
264 int i;
265
266 for (i=0; i < m; i++)
267 print(" %2.2ux", a[i+t]&0xFF);
268 print("\n");
269 }
270 }
271 t += m;
272 }
273 return t;
274 }
275