2 * Remote debugging file system
14 #define DBG if(dbg)fprint
22 /* caching memory pages: a lot of space to avoid serial communications */
24 typedef struct Page Page;
25 struct Page { /* cached memory contents */
37 /* called with pglock locked */
45 p = malloc(sizeof(Page)*Pagequantum);
47 sysfatal("out of memory");
49 for(i=0, q=p; i<Pagequantum-1; i++, q++)
56 freelist = freelist->link;
60 #define PHIINV 0.61803398874989484820
64 return (uint)floor(NHASH*fmod(addr*PHIINV, 1.0));
68 lookup(ulong addr, uchar *val, ulong count)
73 for(p=pgtab[ahash(addr)]; p; p=p->link){
74 if(p->addr == addr && p->count == count){
75 memmove(val, p->val, count);
85 insert(ulong addr, uchar *val, int count)
94 memmove(p->val, val, count);
97 p->len = pgtab[h] ? pgtab[h]->len+1 : 1;
109 for(i=0; i<NHASH; i++){
111 for(;p->link; p=p->link)
137 char* portname = "/dev/eia0";
138 char* textfile = "/386/9pc";
139 char* procname = "1";
146 fprint(2, "usage: rdbfs [-p procnum] [-s srvname] [-t textfile] [serialport]\n");
151 noalarm(void*, char *msg)
153 if(strstr(msg, "alarm"))
159 * send and receive responses on the serial line
172 while(r = recvp(rchan)){
173 DBG(2, "got %F: here goes...", &r->ifcall);
174 if(r->ifcall.count > Readlen)
175 r->ifcall.count = Readlen;
176 r->ofcall.count = r->ifcall.count;
177 if(r->type == Tread && lookup(r->ifcall.offset, (uchar*)r->ofcall.data, r->ofcall.count)){
181 for(tries=0; tries<5; tries++){
182 if(r->type == Twrite){
183 DBG(2, "w%.8lux %.8lux...", (ulong)r->ifcall.offset, *(ulong*)r->ifcall.data);
184 fprint(rfd, "w%.8lux %.8lux\n", (ulong)r->ifcall.offset, *(ulong*)r->ifcall.data);
185 }else if(r->type == Tread){
186 DBG(2, "r%.8lux...", (ulong)r->ifcall.offset);
187 fprint(rfd, "r%.8lux\n", (ulong)r->ifcall.offset);
195 p=Brdline(&rfb, '\n');
198 rerrstr(err, sizeof err);
199 DBG(2, "error %s\n", err);
200 if(strstr(err, "alarm") || strstr(err, "interrupted"))
202 if(Blinelen(&rfb) == 0) // true eof
203 sysfatal("eof on serial line?");
204 Bread(&rfb, buf, Blinelen(&rfb)<sizeof buf ? Blinelen(&rfb) : sizeof buf);
207 p[Blinelen(&rfb)-1] = 0;
210 DBG(2, "serial %s\n", p);
212 if(strtoul(p+1, 0, 16) == (ulong)r->ifcall.offset){
213 /* we know that data can handle Readlen bytes */
214 data = (uchar*)r->ofcall.data;
215 for(i=0; i<r->ifcall.count; i++)
216 data[i] = strtol(p+1+8+1+3*i, 0, 16);
217 insert(r->ifcall.offset, data, r->ifcall.count);
221 DBG(2, "%.8lux ≠%.8lux\n", strtoul(p+1, 0, 16), (ulong)r->ifcall.offset);
222 }else if(p[0] == 'W'){
226 DBG(2, "unknown message\n");
235 attachremote(char* name)
240 print("attach %s\n", name);
241 rfd = open(name, ORDWR);
243 sysfatal("can't open remote %s", name);
245 sprint(buf, "%sctl", name);
246 fd = open(buf, OWRITE);
248 sysfatal("can't set baud rate on %s", buf);
249 write(fd, "B9600", 6);
251 Binit(&rfb, rfd, OREAD);
259 switch((uintptr)r->fid->file->aux){
262 textfd = open(textfile, OREAD);
264 snprint(buf, sizeof buf, "text: %r");
279 switch((uintptr)r->fid->file->aux) {
287 if(sendp(rchan, r) != 1){
288 snprint(buf, sizeof buf, "rdbfs sendp: %r");
294 n = pread(textfd, r->ofcall.data, r->ifcall.count, r->ifcall.offset);
296 rerrstr(buf, sizeof buf);
304 n = sprint(buf, "%-28s%-28s%-28s", "remote", "system", "New");
305 for(i = 0; i < 9; i++)
306 n += sprint(buf+n, "%-12d", 0);
311 respond(r, "unknown read");
320 switch((uintptr)r->fid->file->aux) {
322 if(strncmp(r->ifcall.data, "kill", 4) == 0 ||
323 strncmp(r->ifcall.data, "exit", 4) == 0) {
325 postnote(PNGROUP, getpid(), "umount");
327 }else if(strncmp(r->ifcall.data, "refresh", 7) == 0){
330 }else if(strncmp(r->ifcall.data, "hashstats", 9) == 0){
333 for(i=0; i<NHASH; i++)
335 print("%lud ", pgtab[i]->len);
340 respond(r, "permission denied");
344 if(sendp(rchan, r) != 1) {
345 snprint(buf, sizeof buf, "rdbfs sendp: %r");
362 "fpregs", Xfpregs, 0666,
363 "kregs", Xkregs, 0666,
368 "status", Xstatus, 0444,
374 postnote(PNGROUP, getpid(), "kill");
385 threadmain(int argc, char **argv)
399 procname = EARGF(usage());
402 srvname = EARGF(usage());
405 textfile = EARGF(usage());
421 rchan = chancreate(sizeof(Req*), 10);
422 attachremote(portname);
424 sysfatal("pipe: %r");
426 fmtinstall('F', fcallfmt);
427 proccreate(eiaread, nil, 8192);
429 fs.tree = alloctree("rdbfs", "rdbfs", DMDIR|0555, nil);
430 dir = createfile(fs.tree->root, procname, "rdbfs", DMDIR|0555, 0);
431 for(i=0; i<nelem(tab); i++)
432 closefile(createfile(dir, tab[i].s, "rdbfs", tab[i].mode, (void*)tab[i].id));
434 threadpostmountsrv(&fs, srvname, "/proc", MBEFORE);