This commit is contained in:
Alex Musolino 2018-12-12 12:51:29 +10:30
commit 9b194f23b2
18 changed files with 242 additions and 63 deletions

View file

@ -905,3 +905,8 @@ No.
No.
Not going to explain further.
Get your shit together
oh my, the moral outrage
Let it go, and consider leaving for good.
Do you have evidence?
Diffs are welcome.
Please don't do that.

View file

@ -5248,3 +5248,4 @@ I've been looking into running Plan 9 in JSLinux -- Skip Tavakkolian
i have been looking for an excuse to install 9front.
I'm beginning to wonder if anyone is left that isn't part of 9front? -- Steve Stallion
Having a public mailing list is an invitation for discussion amongst likeminded individuals, not elitist fuckery. -- Steve Stallion, talking about 9fans
[9fans] ..... UNSUBSCRIBE_HELP NEEDED

View file

@ -41,6 +41,8 @@ struct DTName {
/*
we assign all pairs (probe,action-group) (called an enabling or DTEnab) a unique ID called EPID.
we could also use probe IDs and action group IDs but using a single 32-bit ID for both is more flexible/efficient.
epid == -1 indicates a fault record (see below)
*/
struct DTEnab {
u32int epid;
@ -235,6 +237,10 @@ struct DTTrigInfo {
DTChan *ch;
};
/* fault records are used to note when a probe had to be aborted (e.g. because of a page fault) */
enum {
DTFILL = 1, /* illegal address */
};
void dtinit(int);
void dtsync(void);
@ -269,6 +275,7 @@ int dtcread(DTChan *, void *, int);
int dtcaggread(DTChan *, void *, int);
void dtcreset(DTChan *);
void dtcrun(DTChan *, int);
int dtcfault(DTTrigInfo *, int, char *, ...);
/* aggbuf functions */
int dtaunpackid(DTAgg *);

View file

@ -511,6 +511,17 @@ TEXT _wrmsrinst(SB), $0
MOVL BP, AX /* BP set to -1 if traped */
RET
/* fault-proof memcpy */
TEXT peek(SB), $0
MOVL src+0(FP), SI
MOVL dst+4(FP), DI
MOVL cnt+8(FP), CX
CLD
TEXT _peekinst(SB), $0
REP; MOVSB
MOVL CX, AX
RET
/*
* Try to determine the CPU type which requires fiddling with EFLAGS.
* If the Id bit can be toggled then the CPUID instruction can be used

View file

@ -67,6 +67,7 @@ LIB=\
/$objtype/lib/libmp.a\
/$objtype/lib/libfis.a\
/$objtype/lib/libaml.a\
/$objtype/lib/libdtracy.a\
ETHER=`{echo devether.c ether*.c | sed 's/\.c/.'$O'/g'}
AUDIO=`{echo devaudio.c audio*.c | sed 's/\.c/.'$O'/g'}

View file

@ -18,6 +18,7 @@ dev
cap
kprof
fs
dtracy
ether netif
bridge netif log
@ -137,6 +138,9 @@ misc
vgatvp3026 =cur
vgavesa
vgavmware +cur
dtracysys
dtracytimer
ip
tcp

View file

@ -450,6 +450,7 @@ trap(Ureg* ureg)
extern void _forkretiret(void);
extern void _rdmsrinst(void);
extern void _wrmsrinst(void);
extern void _peekinst(void);
extern void load_fs(ulong);
extern void load_gs(ulong);
@ -478,6 +479,11 @@ trap(Ureg* ureg)
ureg->pc += 2;
return;
}
} else if(pc == _peekinst){
if(vno == VectorGPF){
ureg->pc += 2;
return;
}
}
}
@ -712,6 +718,13 @@ fault386(Ureg* ureg, void*)
if(!user){
if(vmapsync(addr))
return;
{
extern void _peekinst(void);
if((void(*)(void))ureg->pc == _peekinst){
ureg->pc += 2;
return;
}
}
if(addr >= USTKTOP)
panic("kernel fault: bad address pc=0x%.8lux addr=0x%.8lux", ureg->pc, addr);
if(up == nil)

View file

@ -449,6 +449,18 @@ TEXT _wrmsrinst(SB), $0
MOVQ BP, AX /* BP set to -1 if traped */
RET
/* fault-proof memcpy */
TEXT peek(SB), 1, $-4
MOVQ RARG, SI
MOVQ dst+8(FP), DI
MOVL cnt+16(FP), CX
CLD
TEXT _peekinst(SB), $0
REP; MOVSB
MOVL CX, AX
RET
TEXT invlpg(SB), 1, $-4
INVLPG (RARG)
RET

View file

@ -65,6 +65,7 @@ LIB=\
/$objtype/lib/libc.a\
/$objtype/lib/libfis.a\
/$objtype/lib/libaml.a\
/$objtype/lib/libdtracy.a\
ETHER=`{cd ../pc; echo devether.c ether*.c | sed 's/\.c/.'$O'/g'}
AUDIO=`{cd ../pc; echo devaudio.c audio*.c | sed 's/\.c/.'$O'/g'}

View file

@ -41,6 +41,7 @@ dev
segment
vmx
dtracy
link
# devpccard
@ -136,6 +137,9 @@ misc
vgavesa
# vgavmware +cur
dtracysys
dtracytimer
ip
tcp
udp

View file

@ -440,6 +440,7 @@ trap(Ureg *ureg)
extern void _rdmsrinst(void);
extern void _wrmsrinst(void);
extern void _peekinst(void);
pc = (void*)ureg->pc;
if(pc == _rdmsrinst || pc == _wrmsrinst){
@ -448,6 +449,11 @@ trap(Ureg *ureg)
ureg->pc += 2;
return;
}
} else if(pc == _peekinst){
if(vno == VectorGPF){
ureg->pc += 2;
return;
}
}
}
@ -672,6 +678,14 @@ faultamd64(Ureg* ureg, void*)
read = !(ureg->error & 2);
user = userureg(ureg);
if(!user){
{
extern void _peekinst(void);
if((void(*)(void))ureg->pc == _peekinst){
ureg->pc += 2;
return;
}
}
if(addr >= USTKTOP)
panic("kernel fault: bad address pc=%#p addr=%#p", ureg->pc, addr);
if(up == nil)

View file

@ -125,9 +125,13 @@ dtkfree(DTKChan *p)
dtktab[idx] = nil;
}
static int dtracyen;
static void
dtracyinit(void)
{
dtracyen = getconf("*dtracy") != nil;
if(!dtracyen) return;
machlocks = smalloc(sizeof(Lock) * conf.nmach);
dtinit(conf.nmach);
}
@ -135,6 +139,8 @@ dtracyinit(void)
static Chan*
dtracyattach(char *spec)
{
if(!dtracyen)
error("*dtracy= not set");
return devattach(L'Δ', spec);
}
@ -512,67 +518,16 @@ dtgetvar(int v)
}
}
int peek(char *, char *, int);
int
dtpeek(uvlong addr, void *buf, int len)
{
if((uintptr)addr != addr || up == nil || !okaddr((uintptr) addr, len, 0)) return -1;
memmove(buf, (void *) addr, len);
return 0;
}
static DTProbe *timerprobe;
static void
dtracytimer(void *)
{
DTTrigInfo info;
memset(&info, 0, sizeof(info));
for(;;){
tsleep(&up->sleep, return0, nil, 1000);
dtptrigger(timerprobe, m->machno, &info);
}
}
static void
timerprovide(DTProvider *prov, DTName)
{
static int provided;
uintptr a;
if(provided) return;
provided = 1;
timerprobe = dtpnew((DTName){"timer", "", "1s"}, prov, nil);
a = addr;
if(len == 0) return 0;
if(a != addr || a > -(uintptr)len || len < 0) return -1;
if(up == nil || up->privatemem || a >= KZERO) return -1;
return peek((void *)a, buf, len) > 0 ? -1 : 0;
}
static int
timerenable(DTProbe *)
{
static int gotkproc;
if(!gotkproc){
kproc("dtracytimer", dtracytimer, nil);
gotkproc=1;
}
return 0;
}
static void
timerdisable(DTProbe *)
{
}
DTProvider dtracyprov_timer = {
.name = "timer",
.provide = timerprovide,
.enable = timerenable,
.disable = timerdisable,
};
extern DTProvider dtracyprov_sys;
DTProvider *dtproviders[] = {
&dtracyprov_timer,
&dtracyprov_sys,
nil,
};

View file

@ -260,7 +260,7 @@ sysdisable(DTProbe *p)
z = systab[i], systab[i] = wraptab[i], wraptab[i] = z;
}
DTProvider dtracyprov_sys = {
DTProvider dtracysysprov = {
.name = "sys",
.provide = sysprovide,
.enable = sysenable,

View file

@ -0,0 +1,56 @@
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "../port/error.h"
#include <dtracy.h>
static DTProbe *timerprobe;
static void
dtracytimer(void *)
{
DTTrigInfo info;
memset(&info, 0, sizeof(info));
for(;;){
tsleep(&up->sleep, return0, nil, 1000);
dtptrigger(timerprobe, m->machno, &info);
}
}
static void
timerprovide(DTProvider *prov, DTName)
{
static int provided;
if(provided) return;
provided = 1;
timerprobe = dtpnew((DTName){"timer", "", "1s"}, prov, nil);
}
static int
timerenable(DTProbe *)
{
static int gotkproc;
if(!gotkproc){
kproc("dtracytimer", dtracytimer, nil);
gotkproc=1;
}
return 0;
}
static void
timerdisable(DTProbe *)
{
}
DTProvider dtracytimerprov = {
.name = "timer",
.provide = timerprovide,
.enable = timerenable,
.disable = timerdisable,
};

View file

@ -58,7 +58,8 @@ collect && section == "misc"{
if($i ~ "[+=]cur")
vgacur[nvgacur++] = $1;
}
}
}else if($1 ~ "^dtracy.*")
dtracyprov[ndtracyprov++] = $1;
}
collect && section == "port"{
@ -190,6 +191,16 @@ END{
printf "%s\n", port[i];
printf "\n";
}
if(ndtracyprov){
printf "#include <dtracy.h>\n";
for(i = 0; i < ndtracyprov; i++)
printf "extern DTProvider %sprov;\n", dtracyprov[i]
printf "DTProvider *dtproviders[] = {\n"
for(i = 0; i < ndtracyprov; i++)
printf "\t&%sprov,\n", dtracyprov[i]
printf "\tnil,\n};\n\n"
}
printf "char* conffile = \"%s/%s\";\n", pwd, ARGV[1];
printf "ulong kerndate = KERNDATE;\n";

View file

@ -462,6 +462,34 @@ parseclause(Clause *cl, uchar *p, uchar *e, Enab *en, Biobuf *bp)
return 0;
}
uchar *
parsefault(uchar *p0, uchar *e)
{
uchar *p;
u32int epid;
u8int type, dummy;
u16int n;
Enab *en;
p = unpack(p0, e, "csci", &type, &n, &dummy, &epid);
if(p == nil) return nil;
en = epidlookup(epid);
switch(type){
case DTFILL: {
u32int pid;
u64int addr;
p = unpack(p, e, "iv", &pid, &addr);
if(p == nil) return nil;
fprint(2, "dtracy: illegal access: probe=%s, pid=%d, addr=%#llx\n", en != nil ? en->probe : nil, pid, addr);
break;
}
default:
fprint(2, "dtracy: unknown fault type %#.2ux\n", type);
}
return p0 + n - 12;
}
int
parsebuf(uchar *p, int n, Biobuf *bp)
{
@ -474,6 +502,11 @@ parsebuf(uchar *p, int n, Biobuf *bp)
while(p < e){
p = unpack(p, e, "iv", &epid, &ts);
if(p == nil) goto err;
if(epid == (u32int)-1){
p = parsefault(p, e);
if(p == nil) goto err;
continue;
}
en = epidlookup(epid);
if(en == nil) goto err;
if(parseclause(en->cl, p - 12, p + en->reclen - 12, en, bp) < 0) return -1;

View file

@ -1414,4 +1414,6 @@ threadmain(int argc, char **argv)
passwdparse(gidtab, readfile(gidfile));
threadpostmountsrv(&sshfssrv, svc, mtpt, MCREATE | mflag);
exits(nil);
}

View file

@ -230,6 +230,55 @@ dtpeekstr(uvlong addr, u8int *v, int len)
#define PUT4(c) *bp++ = c; *bp++ = c >> 8; *bp++ = c >> 16; *bp++ = c >> 24;
#define PUT8(c) PUT4(c); PUT4(c>>32);
int
dtcfault(DTTrigInfo *info, int type, char *fmt, ...)
{
DTBuf *b;
va_list va;
int n;
char *s;
u8int *bp;
u32int l;
uvlong q;
b = info->ch->wrbufs[info->machno];
n = 20;
va_start(va, fmt);
for(s = fmt; *s != 0; s++)
switch(*s){
case 'i': n += 4; break;
case 'p': n += 8; break;
default:
assert(0);
}
va_end(va);
if(b->wr + n > DTBUFSZ)
return -1;
bp = &b->data[b->wr];
PUT4(-1);
PUT8(info->ts);
PUT1(type);
PUT2(n);
PUT1(0);
PUT4(info->epid);
va_start(va, fmt);
for(s = fmt; *s != 0; s++)
switch(*s){
case 'i':
l = va_arg(va, int);
PUT4(l);
break;
case 'p':
q = (uintptr) va_arg(va, void *);
PUT8(q);
break;
}
va_end(va);
assert(bp - b->data - b->wr == n);
b->wr = bp - b->data;
return 0;
}
static int
dtgexec(DTActGr *g, DTTrigInfo *info)
{
@ -265,8 +314,8 @@ dtgexec(DTActGr *g, DTTrigInfo *info)
break;
case ACTTRACESTR:
if(dtpeekstr(v, bp, g->acts[i].size) < 0){
snprint(info->ch->errstr, sizeof(info->ch->errstr), "fault @ %#llux", v);
return -1;
dtcfault(info, DTFILL, "ip", dtgetvar(DTV_PID), v);
return 0;
}
bp += g->acts[i].size;
break;