plan9front/sys/src/cmd/vmx/vmxgdb.c

263 lines
4.3 KiB
C

#include <u.h>
#include <libc.h>
#include <bio.h>
char *vmxroot = "/n/vmx";
Biobuf *bin, *bout;
int regsfd, memfd;
int noack;
void *
emalloc(ulong sz)
{
void *v;
v = malloc(sz);
if(v == nil)
sysfatal("malloc: %r");
memset(v, 0, sz);
setmalloctag(v, getcallerpc(&sz));
return v;
}
int
eBgetc(Biobuf *bp)
{
int c;
c = Bgetc(bp);
if(c < 0) sysfatal("Bgetc: %r");
return c;
}
char *
rpack(void)
{
int c;
char *pkt;
ulong npkt;
u8int csum, csum2;
char buf[3], *p;
while(eBgetc(bin) != '$')
;
if(0){
repeat:
free(pkt);
}
pkt = nil;
npkt = 0;
csum = 0;
while(c = eBgetc(bin)){
if(c == '#') break;
if(c == '$') goto repeat;
csum += c;
if(c == '}'){
c = eBgetc(bin);
if(c == '#') break;
if(c == '$') goto repeat;
csum += c;
c ^= 0x20;
}
if(npkt % 64 == 0)
pkt = realloc(pkt, npkt + 64);
pkt[npkt++] = c;
}
if(npkt % 64 == 0)
pkt = realloc(pkt, npkt + 1);
pkt[npkt] = 0;
buf[0] = eBgetc(bin);
if(buf[0] == '$') goto repeat;
buf[1] = eBgetc(bin);
if(buf[1] == '$') goto repeat;
if(noack) return pkt;
buf[2] = 0;
csum2 = strtol(buf, &p, 16);
if(p != &buf[2] || csum != csum2){
Bputc(bout, '-');
goto repeat;
}
Bputc(bout, '+');
return pkt;
}
int
bflush(Biobufhdr *, void *v, long n)
{
Bflush(bout);
return read(bin->fid, v, n);
}
void
wpack(char *p0)
{
u8int csum;
char *p;
fprint(2, "-> %s\n", p0);
again:
p = p0;
csum = 0;
Bputc(bout, '$');
for(; *p != 0; p++)
switch(*p){
case '$': case '#': case '{': case '*':
Bputc(bout, '{');
Bputc(bout, *p ^ 0x20);
csum += '{' + (*p ^ 0x20);
break;
default:
Bputc(bout, *p);
csum += *p;
}
Bprint(bout, "#%.2uX", csum);
if(noack) return;
for(;;)
switch(eBgetc(bin)){
case '+': return;
case '-': goto again;
case '$': Bungetc(bin); return;
}
}
static char *regname[] = {
"ax", "cx", "dx", "bx",
"sp", "bp", "si", "di",
"pc", "flags", "cs", "ss",
"ds", "es", "fs", "gs",
};
char *
regpacket(void)
{
char *buf;
char rbuf[4096];
int rc;
char *p, *q, *f[2];
int pos, i, l;
uvlong v;
char tbuf[3];
l = 4 * nelem(regname);
buf = emalloc(2 * l + 1);
memset(buf, 'x', 2 * l);
rc = pread(regsfd, rbuf, sizeof(rbuf)-1, 0);
if(rc < 0){
free(buf);
return strdup("");
}
rbuf[rc] = 0;
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);
pos = 0;
for(i = 0; i < nelem(regname); i++){
if(strcmp(f[0], regname[i]) == 0)
break;
pos += 4;
}
if(i == nelem(regname)) continue;
if(f[0][1] == 's' && f[0][2] == 0) v = 0;
l = 4;
while(l--){
sprint(tbuf, "%.2ux", (u8int)v);
((u16int*)buf)[pos++] = *(u16int*)tbuf;
v >>= 8;
}
}
return buf;
}
char *
memread(char *p)
{
char *q;
uvlong addr, count;
char *buf;
int rc, i;
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");
if(count > 65536) count = 65536;
buf = emalloc(2*count+4);
rc = pread(memfd, buf, count, addr);
if(rc <= 0) return strcpy(buf, "E01");
for(i = rc; --i >= 0; ){
sprint(tbuf, "%.2ux", (uchar)buf[i]);
((u16int*)buf)[i] = *(u16int*)tbuf;
}
return buf;
}
void
main(int, char **)
{
char *p, *msg;
bin = Bfdopen(0, OREAD);
if(bin == nil) sysfatal("Bfdopen: %r");
bout = Bfdopen(1, OWRITE);
if(bout == nil) sysfatal("Bfdpen: %r");
Biofn(bin, bflush);
p = smprint("%s/mem", vmxroot);
memfd = open(p, OREAD);
free(p);
if(memfd < 0) sysfatal("open: %r");
p = smprint("%s/xregs", vmxroot);
regsfd = open(p, OREAD);
free(p);
if(regsfd < 0) sysfatal("open: %r");
for(;;){
msg = rpack();
fprint(2, "<- %s\n", msg);
reinterpret:
switch(*msg){
case 'g':
p = regpacket();
wpack(p);
free(p);
break;
case '?':
wpack("S00");
break;
case 'm':
p = memread(msg+1);
wpack(p);
free(p);
break;
case 'q':
if(strncmp(msg, "qSupported", 10) == 0 && (msg[10] == ':' || msg[10] == 0)){
wpack("PacketSize=4096;QStartNoAckMode+");
}else
goto no;
break;
case 'Q':
if(strcmp(msg, "QStartNoAckMode") == 0){
wpack("OK");
noack = 1;
}
break;
case 'H':
msg[0] = msg[1];
msg[1] = 0;
goto reinterpret;
default: no: wpack(""); break;
}
free(msg);
}
}