xref: /inferno-os/utils/acid/rdebug.c (revision 6e425a9de8c003b5a733621a6b6730ec3cc902b8)
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
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
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
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, nb, 0);
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
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
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
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
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
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
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