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";
145 fprint(2, "usage: rdbfs [-p procnum] [-t textfile] [serialport]\n");
150 noalarm(void*, char *msg)
152 if(strstr(msg, "alarm"))
158 * send and receive responses on the serial line
171 while(r = recvp(rchan)){
172 DBG(2, "got %F: here goes...", &r->ifcall);
173 if(r->ifcall.count > Readlen)
174 r->ifcall.count = Readlen;
175 r->ofcall.count = r->ifcall.count;
176 if(r->type == Tread && lookup(r->ifcall.offset, (uchar*)r->ofcall.data, r->ofcall.count)){
180 for(tries=0; tries<5; tries++){
181 if(r->type == Twrite){
182 DBG(2, "w%.8lux %.8lux...", (ulong)r->ifcall.offset, *(ulong*)r->ifcall.data);
183 fprint(rfd, "w%.8lux %.8lux\n", (ulong)r->ifcall.offset, *(ulong*)r->ifcall.data);
184 }else if(r->type == Tread){
185 DBG(2, "r%.8lux...", (ulong)r->ifcall.offset);
186 fprint(rfd, "r%.8lux\n", (ulong)r->ifcall.offset);
194 p=Brdline(&rfb, '\n');
197 rerrstr(err, sizeof err);
198 DBG(2, "error %s\n", err);
199 if(strstr(err, "alarm") || strstr(err, "interrupted"))
201 if(Blinelen(&rfb) == 0) // true eof
202 sysfatal("eof on serial line?");
203 Bread(&rfb, buf, Blinelen(&rfb)<sizeof buf ? Blinelen(&rfb) : sizeof buf);
206 p[Blinelen(&rfb)-1] = 0;
209 DBG(2, "serial %s\n", p);
211 if(strtoul(p+1, 0, 16) == (ulong)r->ifcall.offset){
212 /* we know that data can handle Readlen bytes */
213 data = (uchar*)r->ofcall.data;
214 for(i=0; i<r->ifcall.count; i++)
215 data[i] = strtol(p+1+8+1+3*i, 0, 16);
216 insert(r->ifcall.offset, data, r->ifcall.count);
220 DBG(2, "%.8lux ≠ %.8lux\n", strtoul(p+1, 0, 16), (ulong)r->ifcall.offset);
221 }else if(p[0] == 'W'){
225 DBG(2, "unknown message\n");
234 attachremote(char* name)
239 print("attach %s\n", name);
240 rfd = open(name, ORDWR);
242 sysfatal("can't open remote %s", name);
244 sprint(buf, "%sctl", name);
245 fd = open(buf, OWRITE);
247 sysfatal("can't set baud rate on %s", buf);
248 write(fd, "B9600", 6);
250 Binit(&rfb, rfd, OREAD);
258 switch((uintptr)r->fid->file->aux){
261 textfd = open(textfile, OREAD);
263 snprint(buf, sizeof buf, "text: %r");
278 switch((uintptr)r->fid->file->aux) {
286 if(sendp(rchan, r) != 1){
287 snprint(buf, sizeof buf, "rdbfs sendp: %r");
293 n = pread(textfd, r->ofcall.data, r->ifcall.count, r->ifcall.offset);
295 rerrstr(buf, sizeof buf);
303 n = sprint(buf, "%-28s%-28s%-28s", "remote", "system", "New");
304 for(i = 0; i < 9; i++)
305 n += sprint(buf+n, "%-12d", 0);
310 respond(r, "unknown read");
319 switch((uintptr)r->fid->file->aux) {
321 if(strncmp(r->ifcall.data, "kill", 4) == 0 ||
322 strncmp(r->ifcall.data, "exit", 4) == 0) {
324 postnote(PNGROUP, getpid(), "umount");
326 }else if(strncmp(r->ifcall.data, "refresh", 7) == 0){
329 }else if(strncmp(r->ifcall.data, "hashstats", 9) == 0){
332 for(i=0; i<NHASH; i++)
334 print("%lud ", pgtab[i]->len);
339 respond(r, "permission denied");
343 if(sendp(rchan, r) != 1) {
344 snprint(buf, sizeof buf, "rdbfs sendp: %r");
361 "fpregs", Xfpregs, 0666,
362 "kregs", Xkregs, 0666,
367 "status", Xstatus, 0444,
373 postnote(PNGROUP, getpid(), "kill");
384 threadmain(int argc, char **argv)
398 procname = EARGF(usage());
401 textfile = EARGF(usage());
417 rchan = chancreate(sizeof(Req*), 10);
418 attachremote(portname);
420 sysfatal("pipe: %r");
422 fmtinstall('F', fcallfmt);
423 proccreate(eiaread, nil, 8192);
425 fs.tree = alloctree("rdbfs", "rdbfs", DMDIR|0555, nil);
426 dir = createfile(fs.tree->root, procname, "rdbfs", DMDIR|0555, 0);
427 for(i=0; i<nelem(tab); i++)
428 closefile(createfile(dir, tab[i].s, "rdbfs", tab[i].mode, (void*)tab[i].id));
430 threadpostmountsrv(&fs, nil, "/proc", MBEFORE);