]> git.lizzy.rs Git - plan9front.git/commitdiff
vmx: fix 9p debug server and make it compatible to /proc
authorcinap_lenrek <cinap_lenrek@felloff.net>
Wed, 12 May 2021 16:17:06 +0000 (18:17 +0200)
committercinap_lenrek <cinap_lenrek@felloff.net>
Wed, 12 May 2021 16:17:06 +0000 (18:17 +0200)
The 9p debug server was broken as it assumed the first
tree file added would have a qid of 0 (it has a qid
of 1 as the root directory is using 0 already).

Instead, just compare File* pointers and get rid of
the table (less code).

When passing 64-bit unsigned addresses as 64-bit signed
file offsets, we have to make sure to not pass negative
offsets (filtered out by kernel and lib9p)!
This is solved by clearing and sign bit in encoding and
63-bit sign extension on decoding.

Make the mem file writable (needed for acid).

The 9p debug server provided a single directory containing
mem and regs files. This patch renames the regs file
(which is in vmx specific text format) to "xregs" and
adds "regs" and "kregs" file which use the same format
as exported by the kernels /proc filesystem.

This allows one to bind the vmx directory over a proc
directory and attach acid to a running system like:

mount -b /srv/vmx /proc/1
acid -k -lkernel 1 /sys/src/9/pc64/9pc64

sys/src/cmd/vmx/9p.c
sys/src/cmd/vmx/vmxgdb.c

index 84c3a14194c5fc8816f248ea04a8f4bf52994df1..568cccb51707c664c2cfbfb2c52df379502eca50 100644 (file)
@@ -1,32 +1,95 @@
 #include <u.h>
 #include <libc.h>
 #include <thread.h>
+#include <bio.h>
+#include <mach.h>
 #include <fcall.h>
 #include <9p.h>
 #include "dat.h"
 #include "fns.h"
 
 extern int regsfd;
-char Egreg[] = "the front fell off";
 
-enum {
-       Qregs,
-       Qmem,
-       Qmax
-};
+static char Egreg[] = "the front fell off";
+static File *memfile, *regsfile, *kregsfile, *xregsfile;
+static uchar ureg[1024];
 
-static Dir files[] = {
-       [Qregs] {.name "regs", .mode 0440},
-       [Qmem] {.name "mem", .mode 0440},
-};
+static int
+makeureg(void)
+{
+       extern Mach mi386, mamd64;
+       char rbuf[4096], *p, *q, *f[2];
+       Reglist *r;
+       uvlong v;
+       int rc;
 
-void
+       mach = sizeof(uintptr) == 8 ? &mamd64 : &mi386;
+       memset(ureg, 0, mach->regsize);
+
+       rc = pread(regsfd, rbuf, sizeof(rbuf)-1, 0);
+       if(rc < 0)
+               return -1;
+       rbuf[rc] = 0;
+
+       for(p = rbuf; (q = strchr(p, '\n')) != nil; p = q + 1){
+               *q = 0;
+               if(tokenize(p, f, nelem(f)) < 2) continue;
+               for(r = mach->reglist; r->rname != nil; r++){
+                       if(r->rflags == RINT && cistrcmp(f[0], r->rname) == 0){
+                               v = strtoull(f[1], nil, 0);
+                               switch(r->rformat){
+                               case 'Y':
+                                       PUT64(ureg, r->roffs, v);
+                                       break;
+                               case 'X':
+                                       PUT32(ureg, r->roffs, v);
+                                       break;
+                               case 'x':
+                                       PUT16(ureg, r->roffs, v);
+                                       break;
+                               case 'b':
+                                       PUT8(ureg, r->roffs, v);
+                                       break;
+                               }
+                               break;
+                       }
+               }
+       }
+       return mach->regsize;
+}
+
+static uintptr
+off2addr(vlong off)
+{
+       off <<= 1;
+       off >>= 1;
+       return (uintptr)off;
+}
+
+static void
 srvread(Req *r)
 {
        int rc;
 
-       switch((int)r->fid->qid.path){
-       case Qregs:
+       if(r->fid->file == memfile){
+               r->ofcall.count = vmemread(r->ofcall.data, r->ifcall.count, off2addr(r->ifcall.offset));
+               if(r->ofcall.count == 0)
+                       respond(r, "fault");
+               else
+                       respond(r, nil);
+               return;
+       }
+       if(r->fid->file == regsfile || r->fid->file == kregsfile){
+               rc = makeureg();
+               if(rc < 0){
+                       responderror(r);
+                       return;
+               }
+               readbuf(r, ureg, rc);
+               respond(r, nil);
+               return;
+       }
+       if(r->fid->file == xregsfile){
                rc = pread(regsfd, r->ofcall.data, r->ifcall.count, r->ifcall.offset);
                if(rc < 0)
                        responderror(r);
@@ -34,32 +97,40 @@ srvread(Req *r)
                        r->ofcall.count = rc;
                        respond(r, nil);
                }
-               break;
-       case Qmem:
-               r->ofcall.count = vmemread(r->ofcall.data, r->ifcall.count, r->ifcall.offset);
+               return;
+       }
+       respond(r, Egreg);
+}
+
+static void
+srvwrite(Req *r)
+{
+       if(r->fid->file == memfile){
+               r->ofcall.count = vmemwrite(r->ifcall.data, r->ifcall.count, off2addr(r->ifcall.offset));
                if(r->ofcall.count == 0)
                        respond(r, "fault");
                else
                        respond(r, nil);
-               break;
-       default:
-               respond(r, Egreg);
+               return;
        }
+       respond(r, Egreg);
 }
 
-Srv vmxsrv = {
+static Srv vmxsrv = {
        .read srvread,
+       .write srvwrite,
 };
 
 void
 init9p(char *srvname)
 {
        char *uid;
-       int i;
        
        uid = getuser();
        vmxsrv.tree = alloctree(uid, uid, 0770, nil);
-       for(i = 0; i < Qmax; i++)
-               createfile(vmxsrv.tree->root, files[i].name, uid, files[i].mode, nil);
+       memfile = createfile(vmxsrv.tree->root, "mem", uid, 0660, nil);
+       regsfile = createfile(vmxsrv.tree->root, "regs", uid, 0440, nil);
+       kregsfile = createfile(vmxsrv.tree->root, "kregs", uid, 0440, nil);
+       xregsfile = createfile(vmxsrv.tree->root, "xregs", uid, 0440, nil);
        threadpostmountsrv(&vmxsrv, srvname, nil, 0);
 }
index 07aba25c592b0fcea39d60fa8406a0f4ab051cfa..79f9f464d260e6ed7ee768575d9966b64d8fe755 100644 (file)
@@ -132,7 +132,7 @@ char *
 regpacket(void)
 {
        char *buf;
-       char rbuf[8192];
+       char rbuf[4096];
        int rc;
        char *p, *q, *f[2];
        int pos, i, l;
@@ -148,10 +148,7 @@ regpacket(void)
                return strdup("");
        }
        rbuf[rc] = 0;
-       p = rbuf;
-       for(;; p = q + 1){
-               q = strchr(p, '\n');
-               if(q == nil) break;
+       for(p = rbuf; (q = strchr(p, '\n')) != nil; p = q + 1){
                *q = 0;
                if(tokenize(p, f, nelem(f)) < 2) continue;
                v = strtoull(f[1], nil, 0);
@@ -183,6 +180,11 @@ memread(char *p)
        char tbuf[3];
        
        addr = strtoull(p, &q, 16);
+
+       /* avoid negative file offset */
+       addr <<= 1;
+       addr >>= 1;
+
        if(p == q || *q != ',') return strdup("E99");
        count = strtoull(q + 1, &p, 16);
        if(q+1 == p || *p != 0) return strdup("E99");
@@ -213,7 +215,7 @@ main(int, char **)
        free(p);
        if(memfd < 0) sysfatal("open: %r");
 
-       p = smprint("%s/regs", vmxroot);
+       p = smprint("%s/xregs", vmxroot);
        regsfd = open(p, OREAD);
        free(p);
        if(regsfd < 0) sysfatal("open: %r");