summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2021-05-12 18:17:06 +0200
committercinap_lenrek <cinap_lenrek@felloff.net>2021-05-12 18:17:06 +0200
commit682414ce0d8245bef6c09d9e7ca015331a5ddd35 (patch)
tree5f41a2fdda9d93c3d0de4bc7728744f37097793f
parent532c7479e96e439a13df421d3b9f547cde5b5642 (diff)
downloadplan9front-682414ce0d8245bef6c09d9e7ca015331a5ddd35.tar.xz
vmx: fix 9p debug server and make it compatible to /proc
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
-rw-r--r--sys/src/cmd/vmx/9p.c117
-rw-r--r--sys/src/cmd/vmx/vmxgdb.c14
2 files changed, 102 insertions, 29 deletions
diff --git a/sys/src/cmd/vmx/9p.c b/sys/src/cmd/vmx/9p.c
index 84c3a1419..568cccb51 100644
--- a/sys/src/cmd/vmx/9p.c
+++ b/sys/src/cmd/vmx/9p.c
@@ -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);
}
diff --git a/sys/src/cmd/vmx/vmxgdb.c b/sys/src/cmd/vmx/vmxgdb.c
index 07aba25c5..79f9f464d 100644
--- a/sys/src/cmd/vmx/vmxgdb.c
+++ b/sys/src/cmd/vmx/vmxgdb.c
@@ -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");